Sethiel Sethiel - 5 months ago 11
Java Question

JMX: CPU + Blocked + Wait time = Wall time?

I'm trying to use JMX for measuring how long a method call took and how much of that was CPU time, how much was the thread being blocked and how much was waiting. Ideally, I would expect that CPU time + Block time + Wait time = Wall time, but I've noticed that it's not the case - and it's not just slightly inaccurate timer. For example:

Wall time: 5657.305 ms
CPU time: 4060.000 ms (71.77%)
User time: 3840.000 ms (67.88%)
Block time: 0.000 ms (0.00%)
Wait time: 0.000 ms (0.00%)


So, the question is ... is my presumption that the sum of these times (not User time, that's included in CPU time) should give Wall time wrong? Am I missing something?

Some more details:


  • Wall time: difference of
    System.currentTimeMillis()
    at the method entry and exit

  • CPU time: difference of
    ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()
    at the method entry and exit

  • Block and Wait time: analogically to CPU, with
    ManagementFactory.getThreadMXBean().getThreadInfo(Thread.currentThread().getId()).getBlockedTime()
    and
    getWaitedTime()

  • Yes, I do know that these methods return time in different units (ns/ms), I take that into account.

  • The application is highly hyperthreaded (4000+ threads), but I store all the info per thread, so there shouldn't be any interference between calls from different threads.


nif nif
Answer

CPU time tells you how much time the thread took utilizing the CPU, i.e. actually executing code. Block or wait times increase if the thread had been suspended because of e.g. waiting for I/O or entering a monitor.

However, it's up to the JVM and OS to assign CPU time to threads and processes. They may choose to suspend a thread or process and resume another one at any time, if necessary. So the thread may be in a state where it is neither blocked nor waiting but just not executing. This will add to wall time but not blocked/wait time.

The CPU time value comes from the operating system. I checked OpenJDK 7 for Linux systems, so it might be different on other platforms. Either fast_thread_cpu_time() or slow_thread_cpu_time() is called to calculate CPU time for threads. Both functions are located inhotspot/src/os/linux/vm/os_linux.cpp of the OpenJDK 7 source.

Since OpenJDK uses pthreads on Linux, each Java thread is implemented as a lightweight OS thread. The fast method supported on modern kernels calls pthread_getcpuclockid to retrieve the clock_id for specific thread and then call clock_gettime to retrieve the CPU time for the thread. The slow method will lookup the CPU time values from /proc/self/task/<tid>/stat. Both methods tell you how much time a thread spent consuming CPU in user and system/kernel space.

References: