Question

I've implemented an algorithm using single-threaded Java code. When I run my program using JIT compilation enabled it saturates all 8 cores on my machine. When I run the same program using the -Xint JVM option to disable JIT compilation it runs on a single core as expected.

This is my Java version info:

java version "1.7.0_25"
OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.10.2)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

Why does it seem like my code gets parallelized and where can I find more information on when HotSpot can parallelize code?

Was it helpful?

Solution

Java doesn't auto parallelize code, my guess is that the core saturation you are seeing is the JIT compiling your code. Make your test program input larger so it runs longer(maybe a 2-3 min.) and see if it tails off after a while.

OTHER TIPS

It doesn't automatically parallize your code directly, but it uses much more of the machines resources to make the code run more quickly. It is profiling, compiling, garbage collecting and constantly recompiling based on runtime data. Whenever possible these operations will be done on other CPUs.

It might decide you call a method enough with the same parameter that it completley inlines the result for that parameter, or it might optimize out quite a few if statements in a given method if they are never taken, resulting to the original if you have different parameters. It doesn't want these operations to slow down/block your program, so it does them on different threads.

I'd guess if you ran long enough though you'd see it go back to filling a single cpu.

The answers given above are by and large correct. I'm just answering to complete the picture. Obviously JVM does not auto prallelize the user code and it has it's own threads going on. These threads vary in number, but generally We have following threads. This snapshot of thread stack is taken at the start of the live phase of the hotspot (OpenJDK) JVM. We can see 11 threads here which can easily occupy all the cores of an octacore or a quadcore machine. The thread names also explain their purposes.

Full thread dump OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007ffff0160800 nid=0x2f91 runnable [0x0000000000000000]

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007ffff0158800 nid=0x2f90 waiting on condition [0x0000000000000000]

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007ffff0156000 nid=0x2f8f waiting on condition [0x0000000000000000]

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007ffff0153000 nid=0x2f8e waiting on condition [0x0000000000000000]

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007ffff0150800 nid=0x2f8d waiting on condition [0x0000000000000000]

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007ffff014e800 nid=0x2f8c runnable [0x0000000000000000]

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007ffff0103800 nid=0x2f8b in Object.wait() [0x00007ffff412f000]

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007ffff00fa000 nid=0x2f8a in Object.wait() [0x00007ffff4230000]

"main" #1 prio=5 os_prio=0 tid=0x00007ffff000d000 nid=0x2f86 runnable [0x00007ffff7fca000]

"VM Thread" os_prio=0 tid=0x00007ffff00ef800 nid=0x2f89 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007ffff015f000 nid=0x2f92 waiting on condition 

Similarly, following snapshot of the thread stack shows Garbage Collector in action. This snap was taken after GC invocation. There are 8 threads alone for the GC since I'm running a parallel implementation of GC (I guess GC threads are equal to the number of cores because I'm testing on an octacore machine).

Full thread dump OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007ffff017e800 nid=0xaa1 runnable  (no locks) [0x0000000000000000]

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007ffff016e800 nid=0xaa0 waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007ffff016b800 nid=0xa9f waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007ffff0169800 nid=0xa9e waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007ffff0166000 nid=0xa9d waiting on condition  (no locks) [0x0000000000000000]

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007ffff0164800 nid=0xa9c runnable  (no locks) [0x0000000000000000]

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007ffff0119000 nid=0xa9b in Object.wait()  (no locks) [0x00007fffba33d000]

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007ffff0110000 nid=0xa9a in Object.wait()  (no locks) [0x00007fffba43e000]

"main" #1 prio=5 os_prio=0 tid=0x00007ffff000d000 nid=0xa8b runnable  (no locks) [0x00007ffff7fc9000]

"VM Thread" os_prio=0 tid=0x00007ffff0105000 nid=0xa99 runnable  (no locks) 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007ffff0026800 nid=0xa91 runnable  (no locks) 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007ffff0028800 nid=0xa92 runnable  (no locks) 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007ffff002a800 nid=0xa93 runnable  (no locks) 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007ffff002c800 nid=0xa94 runnable  (no locks) 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007ffff002e800 nid=0xa95 runnable  (no locks) 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007ffff0030800 nid=0xa96 runnable  (no locks) 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007ffff0032800 nid=0xa97 runnable  (no locks) 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007ffff0034800 nid=0xa98 runnable  (no locks) 

"VM Periodic Task Thread" os_prio=0 tid=0x00007ffff017f800 nid=0xaa2 waiting on condition  (no locks) 

Conclusion

Since number of threads vary during runtime and many threads are spawned and killed on the fly, you would almost never see a single core in use by a java program no matter how long it runs.

The above output was generated using GDB and an internal debug API of openJDK. If anybody is interested in knowing more about these threads and their purpose, you can refer to: Thread Management in openJDK

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top