2013-10-03 13 views
5

Mam zaimplementowany algorytm z wykorzystaniem jednowątkowego kodu Java. Kiedy uruchamiam mój program przy włączonej kompilacji JIT, nasyca on wszystkie 8 rdzeni na moim komputerze. Gdy uruchomię ten sam program przy użyciu opcji JVM -Xint, aby wyłączyć kompilację JIT, działa ona zgodnie z oczekiwaniami na pojedynczym rdzeniu.Czy JVM OpenJDK jest paralelnym kodem bajtowym?

To jest moja wersja Java informacji:

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) 

Dlaczego wydaje się jak mój kod pobiera parallelized i gdzie mogę znaleźć więcej informacji na temat kiedy HotSpot może parallelize kodu?

+0

możliwy duplikat [Czy aktualna maszyna wirtualna HotSpot JVM działa domyślnie?] (Http://stackoverflow.com/questions/ 12219424/does-the-current-hotspot-jvm-run-in-parallel-by-default) – Boann

+0

GC jest równoległy i domyślam się, że tworzysz tyle śmieci, ile zużywasz cały procesor. –

+0

Jeśli to GC, dlaczego nie otrzymam tego samego wyniku za pomocą '-Xint'? – user11171

Odpowiedz

7

Java nie autokalizuje kodu, domyślam się, że nasycenie rdzenia, które widzisz, to JIT kompilująca twój kod. Zwiększ wejściowy program testowy, aby działał dłużej (może 2-3 minuty) i sprawdź, czy po pewnym czasie się wyłączy.

+1

Zgaduję, że przebiega funkcja 'Concurrent Mark & ​​Sweep' GC. –

+0

Działa już dobrze 3-5 sekund, ale mógłbym zwiększyć wejście. Zakładałem, że kompilacja JIT zakończy się bardzo szybko, ponieważ implementacja jest niewielka. – user11171

+0

Wydaje mi się mało prawdopodobne, że to GC pochłania wszystkie moje rdzenie, biorąc pod uwagę, że widzę tylko jeden rdzeń wykorzystany bez włączonego JIT. – user11171

2

Nie powoduje automatycznej paralelizacji kodu, ale wykorzystuje znacznie więcej zasobów komputera, aby przyspieszyć działanie kodu. Jest to profilowanie, kompilowanie, usuwanie śmieci i ciągłe rekompilowanie w oparciu o dane uruchomieniowe. O ile to możliwe, operacje te będą wykonywane na innych procesorach.

To może zdecydować, że nazwiesz metodę wystarczająco, z tym samym parametrem, że wypełnisz, podkreśla wynik dla tego parametru, lub może zoptymalizować całkiem sporo instrukcji if w danej metodzie, jeśli nigdy nie zostaną podjęte, w wyniku jeśli masz inne parametry. Nie chce, aby te operacje spowolniły/zablokowały twój program, więc robi to na różnych wątkach.

Zgaduję, że jeśli pobiegniesz wystarczająco długo, zobaczysz, że wraca do wypełnienia pojedynczego procesora.

1

Powyższe odpowiedzi są w większości poprawne. Po prostu odpowiadam, aby ukończyć zdjęcie. Oczywiście JVM nie automatycznie porównuje kod użytkownika i ma własne wątki. Te wątki różnią się liczbą, ale generalnie mamy następujące wątki. Ta migawka stosu wątków jest pobierana na początku fazy na żywo JVM punktu aktywnego (OpenJDK). Widzimy tutaj 11 wątków, które mogą z łatwością zajmować wszystkie rdzenie maszyny octacore lub quadcore. Nazwy nici wyjaśniają również ich cele.

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 

Podobnie, stosując migawka stosu nici pokazuje śmieci kolektor w działaniu. To zdjęcie zostało zrobione po wywołaniu GC. W przypadku GC istnieje tylko 8 wątków, ponieważ używam równoległej implementacji GC (domyślam się, że gwinty GC są równe liczbie rdzeni, ponieważ testuję na maszynie octacore).

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) 

Wnioski

Ponieważ liczba wątków zmieniać się w trakcie wykonywania i wiele wątków zrodził i zginął w locie, to byłoby prawie nigdy nie zobaczyć pojedynczy rdzeń używany przez program Java, bez względu na to jak długo to biegnie.

Powyższe dane wyjściowe zostały wygenerowane przy użyciu GDB i wewnętrznego interfejsu API debugowania openJDK. Jeśli ktokolwiek jest zainteresowany wiedzą na temat tych wątków i ich przeznaczenia, można odnieść się do: Thread Management in openJDK

Powiązane problemy