I find no use for PrintGCApplicationConcurrentTime, but PrintGCApplicationStoppedTime is probably the only number in GC logs that you should sort-of-semi-believe.
I usually start by telling people that they should not blindly believe anything a JVM claims about stopped times (and that includes Zing), and that everyone should use observation-based measurements to keep the logs "honest". This is [partly] what I built jHiccup for. If the GC (and other pause time) logs seem to correlate with your observation-based numbers, then the report is probably fairly accurate. But if/when they don't, believe the observations and not the "I think this is how long I was doing something while I had your application paused" point of view of the JVM.
As to what PrintGCApplicationStoppedTime means: It is supposed to report the time the JVM spent in a stop-the-world safepoint of any kind. In Zing we work hard to make this number encompass the entire safepoint time, end-to-end, inclusively. Specifically, this means the time from when the very first thread was asked to get to a safepoint and stay there, until the very last thread was allowed to leave the safepoint. I believe that OpenJDK and Oracle HotSpot do a decent job of reporting with the same rules for this specific metric.
However, when it comes to other "stop time" reports, you will see potentially huge gaps in how "honest" JVMs are. Our GC times in Zing are as inclusive as PrintGCApplicationStoppedTime, but some others (e.g. the Oracle HotSpot and OpenJDK GCs) often report only the time the GC actually did work while at a safepoint, without including the time it took to get to the safepoint or the time it took to leave it (during which the GC was stalled waiting for all the mutators to arrive at the safepoint).
This may seem like nit-picking, until you realize that in many cases Time To SafePoint (a term we use at Azul so much we abbreviate it as TTSP) can dominate actual observed pause times when those drop into the handful of milliseconds. Note that this is not a "usually", "mostly", or "on the average" statement. It's a "sometimes" statement. While most of your GC-reported pause times may tend to come very close to the associated PrintGCApplicationStoppedTime output, "every once in a while" you can see a huge gap. Those are times when GC dramatically under-reported pause times. It's typically a situation where all threads but one are stalled, waiting for a laggard thread to arrive at the safepoint.
There are many causes for long TTSP in JVMs, and I consider TTSP to be "your next worst enemy" once GC pause work has been eliminated or addressed (as it is with Zing). At Azul, we've spent the past 5+ years beating TTSP times down in the Zing JVM, so we know a lot about them. The simplest example I can give is an array copy. Array copies (in regular HotSpot) do not have a safepoint in the middle. As a copy of a 200MB array represent a period of ~50-300msec (depending on HW) where a global, JVM-wide safepoint cannot be completed. If you are unlucky enough to need to get to a safepoint while one of those is going on (e.g. when GC is triggered, or if you load a class, or if a de-optimization happens), the TTSP can take end up being 10-100x as big as the GC work itself, with practically all your application seeing that length as an observed pause. In such a case, guess what the GC will report, and what PrintGCApplicationStoppedTime will report?
To take the guessing out of it, here is a small demo I happen to have laying around:
/**
* HiccupMeter.java
* Written by Gil Tene of Azul Systems, and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/
*/
public class BogusPauseReportingDemo {
static final int COPYING_ARRAY_LENGTH = 256 * 1024 * 1024;
static final int ALLOCATING_ARRAY_LENGTH = 2 * 1024 * 1024;
static volatile boolean doRun = true;
static class Allocator extends Thread {
volatile byte[] array;
public void run() {
while (doRun) {
array = new byte[ALLOCATING_ARRAY_LENGTH];
}
}
}
static class Copier extends Thread {
volatile byte array1[] = new byte[COPYING_ARRAY_LENGTH];
volatile byte array2[] = new byte[COPYING_ARRAY_LENGTH];
public void run() {
while (doRun) {
System.arraycopy(array1, 0, array2, 0, COPYING_ARRAY_LENGTH);
}
}
}
public static void main(String [] args) {
Allocator allocator = new Allocator();
Copier copier = new Copier();
long runTimeMsec = 10000;
for (int i = 0; i < args.length; ++i) {
if (args[i].equals("-t")) {
runTimeMsec = Integer.parseInt(args[++i]);
} else {
System.out.println("Usage: java BogusPauseReportingDemo [-t runTimeMsec]");
System.exit(1);
}
}
System.out.println("BogusPauseReportingDemo started, will run for " + runTimeMsec + " msec");
allocator.start();
copier.start();
try {
Thread.sleep(runTimeMsec);
} catch (InterruptedException ex) {
}
doRun = false;
System.out.println("BogusPauseReportingDemo done...");
}
}
Here is sample output from a run with Oracle HotSpot on a 2 socket X5690 server:
(Note the occasional >10:1 under-reporting of pause time in the GC lines, compared to the application stopped lines)
qalperf2.azulsystems.com-9% ${JAVA_HOME}/bin/java -Xmx1g -verbosegc -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime BogusPauseReportingDemo -t 5000
BogusPauseReportingDemo started, will run for 5000 msec
0.853: [GC 784634K->526624K(1004928K), 0.0046340 secs]
Total time for which application threads were stopped: 0.0129990 seconds
1.172: [GC 787597K->526656K(1004928K), 0.0040280 secs]
Total time for which application threads were stopped: 0.0084650 seconds
1.492: [GC 788511K->526656K(1004928K), 0.0029970 secs]
Total time for which application threads were stopped: 0.0149710 seconds
1.822: [GC 787908K->526736K(1004928K), 0.0051360 secs]
Total time for which application threads were stopped: 0.0053990 seconds
2.136: [GC 787592K->526720K(957248K), 0.0024930 secs]
Total time for which application threads were stopped: 0.0028780 seconds
2.446: [GC 781160K->526640K(1002496K), 0.0051180 secs]
Total time for which application threads were stopped: 0.0123830 seconds
2.852: [GC 826026K->526592K(1002496K), 0.0027390 secs]
Total time for which application threads were stopped: 0.0214070 seconds
3.250: [GC 825849K->526592K(994112K), 0.0031760 secs]
Total time for which application threads were stopped: 0.0416690 seconds
3.648: [GC 817568K->526592K(986432K), 0.0035210 secs]
Total time for which application threads were stopped: 0.0472290 seconds
4.051: [GC 811367K->526592K(976960K), 0.0047570 secs]
Total time for which application threads were stopped: 0.0552170 seconds
Total time for which application threads were stopped: 0.0548840 seconds
4.452: [GC 803138K->528640K(1042112K), 0.0048630 secs]
Total time for which application threads were stopped: 0.0277950 seconds
4.932: [GC 868662K->528640K(1031680K), 0.0043900 secs]
Total time for which application threads were stopped: 0.0375160 seconds
BogusPauseReportingDemo done...