2011-04-19 11 views
9

Używam serwera Java, który używa CMS dla dzierżawionego kolektora. Działając pod obciążeniem, widzę młode kolekcje o każdej 1s i na stałe (równoczesne) co 5m. To jest dobre.CMS Java jest ignorowany i uzyskuje pełne GC Zamiast tego

Kiedy biegnę z rzeczywistym ruchu około 1/2 pojemności, mam młodych zbiory o każdy 4S i zwyczajnych (! Równoległe, zatrzymać świat!) O każdym 7m. Dlaczego JVM decyduje się na zrobienie pełnych zatrzymań na świecie zamiast korzystania z kolektora CMS?

Z gc.log można zobaczyć „Full GC” prowadzony i przejmując 3s, aby zakończyć. Tutaj nie ma awarii w trybie równoczesnym. Nic wyraźnie nie żąda kolekcji.

1350.596: [GC 1350.596: [ParNew 
Desired survivor size 119275520 bytes, new threshold 3 (max 3) 
- age 1: 34779376 bytes, 34779376 total 
- age 2: 17072392 bytes, 51851768 total 
- age 3: 24120992 bytes, 75972760 total 
: 1765625K->116452K(1864192K), 0.1560370 secs] 3887120K->2277489K(5009920K), 0.1561920 secs] [Times: user=0.40 sys=0.04, real=0.16 secs] 
1355.106: [GC 1355.107: [ParNew 
Desired survivor size 119275520 bytes, new threshold 3 (max 3) 
- age 1: 44862680 bytes, 44862680 total 
- age 2: 20363280 bytes, 65225960 total 
- age 3: 16908840 bytes, 82134800 total 
: 1747684K->123571K(1864192K), 0.1068880 secs] 3908721K->2307790K(5009920K), 0.1070130 secs] [Times: user=0.29 sys=0.04, real=0.11 secs] 
1356.106: [Full GC 1356.106: [CMS: 2184218K->1268401K(3145728K), 3.0678070 secs] 2682861K->1268401K(5009920K), [CMS Perm : 145090K->145060K(262144K)], 3.0679600 secs] [Times: user=3.05 sys=0.02, real=3.07 secs] 
1361.375: [GC 1361.375: [ParNew 
Desired survivor size 119275520 bytes, new threshold 3 (max 3) 
- age 1: 33708472 bytes, 33708472 total 
: 1631232K->84465K(1864192K), 0.0189890 secs] 2899633K->1352866K(5009920K), 0.0191530 secs] [Times: user=0.19 sys=0.00, real=0.02 secs] 
1365.587: [GC 1365.587: [ParNew 
Desired survivor size 119275520 bytes, new threshold 3 (max 3) 
- age 1: 33475320 bytes, 33475320 total 
- age 2: 22698536 bytes, 56173856 total 
: 1715697K->67421K(1864192K), 0.0229540 secs] 2984098K->1335822K(5009920K), 0.0231240 secs] [Times: user=0.25 sys=0.00, real=0.03 secs] 

Oto flagi JVM:

-server -Xss256K -Xms5120M -Xmx5120M -XX:NewSize=2048M -XX:MaxNewSize=2048M 
-XX:SurvivorRatio=7 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 
-XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=80 
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSFullGCsBeforeCompaction=1 
-XX:SoftRefLRUPolicyMSPerMB=73 -verbose:gc -XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -Xloggc:logs/gc.log 
-XX:MaxPermSize=256m -XX:PermSize=256m -XX:MaxTenuringThreshold=3 
+0

Coś ciekawego ... Po około 2800 sekundach (+/- 200s) CMS zaczyna być ponownie używany. Zazwyczaj 1 lub 2 próby zostają przerwane z przerwanym "trybem współbieżnym", a po tym wszystkim udane CMS. Ruch w tym czasie nie ulegał zmianie. 2415,457 - Pełne GC ... młodzi zbiory ... 2684,320 - CMS-początkowy znak (pierwszy znak CMS nigdzie w dzienniku) 2684,436 - Pełne GC (tryb równoległy przerwany) ... młody .. . ... kolejny CMS przerwany ... ... młody ... 3224,451 - CMS-początkowy znak 3234,855 - młody 3230,254 - CMS-uwaga 3231,972 - CMS-reset (zrobione) ... wszystko dobrze ... –

+0

Według [kodu CMS] (http://cr.openjdk.java.net/~jrose/6863023/diff-04-to-05/raw_files/new/src/share/vm/gc_implementation /concurrentMarkSweep/concurrentMarkSweepGeneration.cpp), komunikat "przerwany w trybie współbieżnym" e występuje z powodu (a) 'GCCause :: is_user_requested_gc' lub (b)' GCCause :: is_serviceability_requested_gc'. Oznacza to, że przyczyną jest (a) '_java_lang_system_gc' lub' _jvmti_force_gc', lub (b) '_jvmti_force_gc',' _heap_inspection' lub '_heap_dump'.Wydaje się, że to samo może być źródłem zarówno pełnego GC, jak i przerw, ale żadna z nich nie powinna mieć miejsca. –

+0

Oto pierwsze 8000 sekund [pliku logu GC] (http://www.backgroundexposure.com/gc.log.txt) z jednego serwera, jeśli jesteś zainteresowany. –

Odpowiedz

2

Jeśli przestrzeń przeżył nie jest wystarczająco duży, może to wywołać Pełny GC. (Wygląda na to, że narzeka na stosunek do przeżycia)

Albo musisz zmniejszyć współczynnik przeżycia, albo lepszym rozwiązaniem może być zwiększenie rozmiaru NewSize, aby mniej obiektów przetrwało z przestrzeni eden. Mam przestrzeń Eden 6 GB;)

+0

Przestrzeń ocalałego utrzyma się na ogół w okolicach 4-6 cykli, ale ponieważ nie zmniejsza jej ilość w każdym cyklu, ograniczam ją do 3 cykli, aby zmniejszyć ilość zbędnych memcpów. –

+0

BTW, mój rozmiar Eden jest wybierany, aby powodować kolekcje nie częściej niż co 1s przy pełnym obciążeniu i ze średnim czasem zatrzymania na świecie wynoszącym 50 ms. Zwykle odpowiedzi są udzielane w czasie krótszym niż 50 ms przy 99,9% poniżej 250 ms. –

+0

BTW: Tworząc minimum obiektów, przestrzeń Eden wystarcza na cały dzień. Mam jedną pełną GC każdej nocy o 5 rano, bez żadnych mniejszych GC. ;) Czas odpowiedzi jest krótszy niż 0,1 ms i jest to duży procent czasu. –

1

wydaje mi się, przypominam sobie podobnego zjawiska w ubiegłym roku podczas strojenia dużej sterty uniknięcie pełnej GC. Myślę, że możesz chcieć zmniejszyć rozmiar eden. To dość duże w porównaniu do pokolenia na stałe.

co wierzę być może dzieje się to, że więcej od swojej eden dostaje „stary” w raz z 1/2 prędkości ruchu, niż ma to miejsce przy pełnej prędkości (w przypadku gdy nie są one przeżyły). Co oznacza, że ​​więcej trzeba przenieść na stałe na raz. A jeśli nie będzie pasować w tym czasie, może wywołać pełny GC, aby zrobić miejsce.

Dla odniesienia Oto co używamy teraz do 6GB na stosach 24GB:

-XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:+UseCompressedOops 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+DisableExplicitGC 
-XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled 
-XX:+CMSScavengeBeforeRemark -XX:CMSInitiatingOccupancyFraction=68 
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:logs/gc.log 

Jest dość podobny do Ciebie już. Zaletą korzystania ze wszystkich współczynników jest to, że można łatwo zmienić wielkość sterty i (ogólnie) odpowiednio skalować. Jeszcze jedna uwaga jest taka, że ​​-XX:+UseCompressedOops może zwykle zużywać o 40% mniej pamięci, redukując adresowanie 64-bitowe do 32-bitowych (działa tylko do 32 GB).

+0

Pełna wartość GC spowodowana brakiem promowania obiektów Young to Tenured pojawiłaby się w dzienniku jako "awaria trybu współbieżnego", której nie ma. Widziałem wiele z nich w przeszłości; obłożenie = 80 jest wynikiem ostrożnego strojenia. Moje prośby prawie zawsze odpowiadają w <250ms, więc większość Edenu jest wyrzucana natychmiast, a mniej niż 10% zostaje skopiowane do ocalałego. Około 1/4 do 1/2 tego jest wyrzucane w następnym cyklu, po czym nie zmniejsza dużo, bez względu na to, ile kopii jest dozwolonych (stąd TenuringThreshold = 3). Mniej niż 5% przestrzeni w Edenie zostaje przydzielone. –

+0

Najwyraźniej mówiłem zbyt szybko. Obniżenie mojej "frakcji zajętości" do 60 rzeczywiście to powstrzymało. Być może nie jest to uważane za "awarię trybu współbieżnego", chyba że JVM spróbuje co najmniej jedną kolekcję CMS od momentu uruchomienia (chociaż dlaczego nie, nie rozumiem). Nawet liczniki wewnętrzne JVM nie liczyły się jako takie, komunikaty logów lub nie. Teraz ... Dlaczego przeniesienie 15-30MB do świeżo strzeżonej przestrzeni 3G ma problem z zajmowaniem 70 osób, ale pracuje z 65? 30 MB to tylko 1% sieci 3G. –

Powiązane problemy