2013-10-03 32 views
5

我已經實現了一個使用單線程Java代碼的算法。當我使用啓用JIT編譯來運行我的程序時,它會飽和我機器上的所有8個內核。當我使用-Xint JVM選項運行相同的程序來禁用JIT編譯時,它會按預期在單個內核上運行。OpenJDK JVM是否並行化字節碼?

這是我的Java版本信息:

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) 

爲什麼它似乎像我的代碼被並行化和我在哪裏可以找到熱點時,可以並行代碼的更多信息?

+0

可能的重複[當前HotSpot JVM默認並行運行嗎?](http://stackoverflow.com/questions/ 12219424/does-the-current-hotspot-jvm-run-in-parallel-by-default) – Boann

+0

GC是並行的,我的猜測是你正在使用所有的CPU創建如此多的垃圾。 –

+0

如果是GC,那麼我爲什麼不用'-Xint'獲得相同的結果? – user11171

回答

7

Java不會自動並行化代碼,我的猜測是你看到的核心飽和度是JIT編譯你的代碼。讓您的測試程序輸入更大,以便運行時間更長(可能需要2-3分鐘),並查看一段時間後它是否會縮短。

+1

我的猜測是'Concurrent Mark&Sweep' GC運行。 –

+0

它已經運行了3-5秒,但我可以使輸入變大。我認爲JIT編譯會很快完成,因爲實現很小。 – user11171

+0

考慮到我看到只有一個沒有啓用JIT的核心,我認爲GC不太可能佔用我所有的核心。 – user11171

2

它不會自動將代碼直接並列,但它會使用更多的機器資源以使代碼更快地運行。它基於運行時數據進行性能分析,編譯,垃圾收集和不斷重新編譯。只要有可能,這些操作將在其他CPU上完成。

它可能決定您調用足夠的方法,使用完全相同的參數來內聯該參數的結果,或者可能會優化多個if語句,如果它們從未被採用,則會導致原始如果你有不同的參數。它不希望這些操作減慢/阻止你的程序,所以它會在不同的線程上執行它們。

我猜如果你跑了足夠長的時間,雖然你會看到它回到填補一個CPU。

1

上面給出的答案是正確的。我只是回答完成圖片。顯然,JVM不會自動並行化用戶代碼,並且它自己的線程正在進行。這些線程數量有所不同,但通常我們有以下線程。線程堆棧的這個快照是在熱點(OpenJDK)JVM的活動階段開始時獲取的。我們可以在這裏看到11個線程,它們可以輕鬆佔用八核或四核機器的所有內核。線程名稱也解釋了它們的用途。

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 

類似地,線程堆棧的以下快照顯示在動作垃圾收集。這個快照是在GC調用後進行的。 GC有8個線程,因爲我正在運行GC的並行實現(我猜測GC線程等於核心數,因爲我正在測試八核機器)。

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) 

結論

由於線程的數目在運行時有所不同,許多線程啓動,並打死蒼蠅,你幾乎從來沒有看到一個Java程序使用單核心無論多久它運行。

上面的輸出是使用GDB和openJDK的內部調試API生成的。如果有人有興趣瞭解更多關於這些線程及其用途的信息,可以參考:Thread Management in openJDK

相關問題