2013-01-15 12 views
7

Mam aplikację java, która wykonuje pewną pracę z określonym wykorzystaniem pamięci. Zauważyłem, że kiedy uruchamiam aplikację z prawie 80% instalacją sterty dla młodego pokolenia, moje aplikacje działają znacznie szybciej niż domyślne ustawienia 1: 2. W szczególności mam uruchomienia JVM z:Duża nowa wielkość stosu java powoduje, że proces jest nieodpowiedni przez długi czas

java -XX:NewSize=10G -XX:+UseParallelOldGC -server -Xmx12G -Xms12G

Serwer posiada co najmniej 14 GB wolnej pamięci fizycznej, tak powinno być na tyle myślę, na sterty Java i „innych” przestrzeni.

Teraz dzieje się tak:

25.289: [GC [PSYoungGen: 7872317K->1058813K(9175040K)] 7872533K->1059029K(11272192K), 0.1876420 secs] [Times: user=1.92 sys=1.01, real=0.18 secs] 
28.918: [GC [PSYoungGen: 8923133K->1091124K(9175040K)] 8923349K->1091340K(11272192K), 0.2206940 secs] [Times: user=1.92 sys=1.70, real=0.22 secs] 
32.946: [GC [PSYoungGen: 8955444K->1060567K(9175040K)] 8955660K->1060783K(11272192K), 0.1804050 secs] [Times: user=2.86 sys=0.01, real=0.18 secs] 
37.166: [GC [PSYoungGen: 8924887K->1080085K(8329344K)] 8925103K->1080301K(10426496K), 0.1891370 secs] [Times: user=3.08 sys=0.01, real=0.19 secs] 
41.326: [GC [PSYoungGen: 8098709K->1088209K(8106880K)] 8098925K->1088425K(10204032K), 0.2284920 secs] [Times: user=3.49 sys=0.04, real=0.23 secs] 
45.779: [GC [PSYoungGen: 8106833K->59784K(8672768K)] 8107049K->1039790K(10769920K), 0.2195770 secs] [Times: user=2.02 sys=1.91, real=0.22 secs] 
49.963: [GC [PSYoungGen: 6953352K->75043K(8689664K)] 7933358K->1062837K(10786816K), 0.0384440 secs] [Times: user=0.63 sys=0.01, real=0.04 secs] 
54.171: [GC [PSYoungGen: 6968611K->140387K(8737984K)] 7956405K->1129497K(10835136K), 0.0715690 secs] [Times: user=1.12 sys=0.00, real=0.07 secs] 
58.455: [GC [PSYoungGen: 7093923K->194024K(8701312K)] 8083033K->1205300K(10798464K), 0.0952730 secs] [Times: user=1.66 sys=0.02, real=0.10 secs] 
62.825: [GC [PSYoungGen: 7147560K->122912K(8840256K)] 8158836K->1298466K(10937408K), 0.1671770 secs] [Times: user=2.89 sys=0.10, real=0.16 secs] 
67.302: [GC [PSYoungGen: 7270304K->117888K(8792896K)] 8445858K->1377169K(10890048K), 0.1156200 secs] [Times: user=1.98 sys=0.05, real=0.12 secs] 
71.785: [GC [PSYoungGen: 7265280K->119002K(8950720K)] 8524561K->1464556K(11047872K), 0.1152940 secs] [Times: user=1.97 sys=0.09, real=0.11 secs] 
76.448: [GC [PSYoungGen: 7477018K->206455K(8893056K)] 8822572K->1642652K(10990208K), 0.1607870 secs] [Times: user=2.63 sys=0.06, real=0.16 secs] 
81.051: [GC [PSYoungGen: 7564471K->114350K(9084608K)] 9000668K->1649307K(11181760K), 0.1145730 secs] [Times: user=1.89 sys=0.16, real=0.12 secs] 
86.020: [GC [PSYoungGen: 7739630K->125895K(9026432K)] 9274587K->1743248K(11123584K), 0.1125030 secs] [Times: user=1.95 sys=0.06, real=0.11 secs] 
91.007: [GC [PSYoungGen: 7751175K->202320K(9221952K)] 9368528K->1905769K(11319104K), 0.1523180 secs] [Times: user=2.58 sys=0.06, real=0.15 secs] 
95.817: [GC [PSYoungGen: 8085136K->327488K(9146624K)] 9788585K->2203753K(11243776K), 0.2542190 secs] [Times: user=4.44 sys=0.10, real=0.25 secs] 
96.071: [Full GC [PSYoungGen: 327488K->0K(9146624K)] [ParOldGen: 1876265K->1032314K(2097152K)] 2203753K->1032314K(11243776K) [PSPermGen: 27528K->21277K(48128K)], 1.4351920 secs] [Times: user=5.12 sys=0.36, real=1.44 secs] 

Jak widać, wszystko jest w porządku i Full GC działa OK. Ale następna operacja GC (nie pełna) znacznie zwiększa użycie pamięci procesu, a serwer zaczyna używać swap.

102.741: [GC-- [PSYoungGen: 7882816K->7882816K(9146624K)] 8915130K->9979962K(11243776K), 133.4433280 secs] [Times: user=69.73 sys=602.83, real=133.46 secs] 
236.191: [Full GC [PSYoungGen: 7882816K->0K(9146624K)] [ParOldGen: 2097146K->1069237K(2097152K)] 9979962K->1069237K(11243776K) [PSPermGen: 21277K->21251K(48192K)], 6.9285350 secs] [Times: user=12.75 sys=0.23, real=6.93 secs] 

Pytanie brzmi - dlaczego? O ile rozumiem, pełna gc jest najbardziej bolesnym punktem w przetwarzaniu gc. Dlaczego więc aplikacja przestaje działać po pełnym wykonaniu polecenia gc?

Odpowiedz

2

Biorąc pod uwagę bardzo wysoki czas systemowy (znacznie wyższy niż czas użytkownika) Sugeruje to, że coś się dzieje w systemie operacyjnym. Mówisz, że masz dużo pamięci, ale jeśli nawet niewielka część JVM zostanie zamieniona na dysk, może zabić czasy GC.

Proponuję, aby zmniejszyć łączny rozmiar sterty, aby zapewnić więcej wolnej pamięci dla pamięci podręcznej OS/dysku/innych programów.

Aby jeszcze bardziej usprawnić aplikację, użyłbym profilera pamięci (najprawdopodobniej trzeba użyć komercyjnego, zrobi to licencja eval) Wydaje się, że generujesz 1,5 GB na sekundę śmieci, co jest niesamowitą sumą. Jeśli możesz przyciąć go do kilku 100 MB na sekundę, powinno to znacząco poprawić wydajność (a także zmniejszyć opóźnienia).

BTW: -server powinien być domyślny na każdym komputerze 64-bitowym.

2

Pracowałem przez kilka lat z aplikacją, która wymaga wielkości sterty i odświeżenia pamięci podobnej do twojej (stertka 20 GB, 1 GB +/sekunda rezygnacji). Jak powiedział @Peter Lawrey, jeśli możesz zmniejszyć albo całkowite zużycie pamięci, albo rezygnację, wyjdziesz naprzód (FYI - mam szczęście z profilerem YourKit, bez związku z firmą, ale moje doświadczenie było dobrze.YMMV.)

Ale jeśli nie możesz zmniejszyć zużycia sterty lub rezygnacji, polecam rozważyć więcej tuningu GC. Oczywiście zrobiłeś; Oto kilka rzeczy, które zadziałały dla nas:

  • Zmniejsz rozmiar nowej generacji (obecnie przeznaczasz 10 GB i gromadzisz prawie wszystko co kilka sekund. Możesz lepiej przydzielić 1-2 . GB i zbierać częściej Pozwoliłoby to na zmniejszenie całkowitej wielkości sterty, jak również i prawdopodobnie uniknąć swapping

-XX:+PrintGCDetails -XX:+PrintGCDateStamps. - czasami miło jest mieć rzeczywiste daty dzienniki GC)

-XX:+UseConcMarkSweepGC - Współbieżny GC starszej generacji pochłania więcej procesora, ale zapewnia krótsze przerwy. Dla naszej aplikacji to nasze preferencje i wygląda na to, że to prawdopodobnie także twoje.

Możesz także ustawić -XX:ParallelGCThreads=<threads> na coś rozsądnego dla twojego sprzętu (używamy 6 na 12-rdzeniowych maszynach, ale nie wiem, że dostroiliśmy to optymalnie).

Powiązane problemy