Po wielu poszukiwaniach najlepsze wyjaśnienie, jakie znalazłem, pochodzi z witryny Java Performance Tuning w pytaniu miesiąca: 1.4.1 Algorytmy zbierania śmieci, 29 stycznia 2003 r.
Algorytmy zbierania śmieci młodej generacji
Kolektor (oryginalna) kopiowanie (domyślnie włączone). Po uruchomieniu tego modułu zbierającego wszystkie wątki aplikacji są zatrzymywane, a kolekcja kopiowania przebiega przy użyciu jednego wątku (co oznacza tylko jeden procesor, nawet jeśli jest to maszyna wieloprocesorowa). Nazywa się to zbieraniem typu „stop-the-world”, ponieważ w zasadzie maszyna JVM wstrzymuje wszystko inne do czasu zakończenia zbierania.
Równolegle kolektor kopiowania (uaktywnione za -xx: + UseParNewGC). Podobnie jak oryginalny kolekcjoner kopii, jest to kolekcjoner typu stop-the-world. Jednak ten kolektor równolegle kopiuje kolekcję w wielu wątkach, co jest bardziej wydajne niż oryginalny moduł zbierający kopiowanie jednowątkowe dla maszyn z wieloma procesorami (choć nie dla maszyn z jednym procesorem). Algorytm ten potencjalnie przyspiesza zbieranie danych przez młode pokolenie o współczynnik równy liczbie dostępnych procesorów w porównaniu z oryginalnym kolektorem kopiowania z pojedynczym wątkiem.
Równolegle kolektor przedmuch (uaktywnione za -xx: UseParallelGC). Jest to podobne do poprzedniego kolektora równoległego kopiowania, ale algorytm jest dostrojony do stosów gigabajtów (ponad 10 GB) na maszynach wieloprocesorowych. Ten algorytm zbierania ma na celu maksymalizację przepustowości przy jednoczesnej minimalizacji przerw. Posiada opcjonalną strategię dostrajania adaptacyjnego, która automatycznie zmienia rozmiar przestrzeni sterty. Jeśli używasz tego kolektora, możesz używać tylko oryginalnego kolektora mark-sweep w starej generacji (tzn. Współbieżny kolektor nowej generacji nie może współpracować z tym kolektorem młodej generacji).
Z tych informacji wynika, że główna różnica (poza współpracą z CMS) polega na tym, że UseParallelGC obsługuje ergonomię, a UseParNewGC nie.
Równoległe GC
UseParNewGC
Być może najłatwiejszym sposobem zrozumienia były kombinacje algorytmów zbierania śmieci stworzone przez Alexeya Ragozina
Pokaż fragment kodu
<table border="1" style="width:100%"> <tr> <td align="center">Young collector</td> <td align="center">Old collector</td> <td align="center">JVM option</td> </tr> <tr> <td>Serial (DefNew)</td> <td>Serial Mark-Sweep-Compact</td> <td>-XX:+UseSerialGC</td> </tr> <tr> <td>Parallel scavenge (PSYoungGen)</td> <td>Serial Mark-Sweep-Compact (PSOldGen)</td> <td>-XX:+UseParallelGC</td> </tr> <tr> <td>Parallel scavenge (PSYoungGen)</td> <td>Parallel Mark-Sweep-Compact (ParOldGen)</td> <td>-XX:+UseParallelOldGC</td> </tr> <tr> <td>Serial (DefNew)</td> <td>Concurrent Mark Sweep</td> <td> <p>-XX:+UseConcMarkSweepGC</p> <p>-XX:-UseParNewGC</p> </td> </tr> <tr> <td>Parallel (ParNew)</td> <td>Concurrent Mark Sweep</td> <td> <p>-XX:+UseConcMarkSweepGC</p> <p>-XX:+UseParNewGC</p> </td> </tr> <tr> <td colspan="2">G1</td> <td>-XX:+UseG1GC</td> </tr> </table>
Wniosek:
źródło
-XX:-UseParallelGC
.-XX:+UseParallelGC
prowadzi do użycia równoległego GC zarówno dla młodego, jak i starego GC dla nowoczesnych maszyn JVM. Zobacz bugs.openjdk.java.net/browse/…UseParNewGC zwykle znany jako „równoległy zbieracz młodego pokolenia” jest taki sam pod każdym względem jak równoległy moduł zbierający elementy bezużyteczne (-XX: + UseParallelGC), z wyjątkiem tego, że jest bardziej wyrafinowany i wydajny. Może być również używany z „współbieżnym kolektorem o niskiej przerwie”.
Zobacz temat Java GC FAQ , pytanie 22, aby uzyskać więcej informacji.
Zauważ, że w UseParNewGC jest kilka znanych błędów
źródło
Użycie -XX: + UseParNewGC razem z -XX: + UseConcMarkSweepGC spowoduje dłuższy czas przerwy dla drugorzędnych GC w porównaniu z -XX: + UseParallelGC.
Dzieje się tak, ponieważ promocja obiektów z Young do Old Generation będzie wymagała uruchomienia algorytmu Best-Fit (ze względu na fragmentację starej generacji) w celu znalezienia adresu dla tego obiektu.
Uruchamianie takiego algorytmu nie jest wymagane w przypadku korzystania z -XX: + UseParallelGC, ponieważ + UseParallelGC można skonfigurować tylko z MarkandCompact Collector, w którym to przypadku nie ma fragmentacji.
źródło