Jak przekonać Java Garbage Collector do działania, gdy zestaw roboczy jest mały?
To jest kolejne pytanie „proszę mi powiedzieć, jak wymusić uruchomienie garbage collectora Java”. W naszej aplikacji uważam, że mamy ku temu dobre powody.
Jest to aplikacja serwerowa, która zazwyczaj ma około 5 milionów obiektów na żywo. Raz na 5 minut wykonujemy zadanie analityczne, które trwa ~ 60 sekund. Jeśli pełny GC zostanie wyzwolony podczas analizy, będzie około 40 milionów obiektów na żywo. Dodatkowe 35M obiekty stają się śmieciami po zakończeniu analizy. Serwer musi reagować na żądania przez cały czas (nawet podczas analizy).
Odkryliśmy, że pełne GC trwa około 1,5 sekundy, jeśli zostanie wywołane, gdy analiza nie jest uruchomiona, ale około 15 sekund, gdy analiza jest uruchomiona. Niestety, nasz wzorzec alokacji jest taki, że pełne GC zwykle uruchamiają się podczas analizy, nawet jeśli analiza trwa tylko 20% czasu. (Co trzeci lub czwarty przebieg analizy uruchamia pełny GC.)
Dodałem kod do wywołania pogardzanego System.gc () tuż przed rozpoczęciem analizy, jeśli wolne miejsce w starej generacji jest poniżej pewnego progu (5 GB). Korzyść była bardzo znacząca: otrzymujemy 1,5-sekundową przerwę zamiast 15-sekundowej przerwy, a my uwalniamy więcej śmieci do okazji. Czasami jednak wywołanie System.gc () jest ignorowane i kończymy 15-sekundową pauzą kilka minut później, gdy GC jest uruchamiany automatycznie.
Moje pytanie więc: czy jest coś, co możemy zrobić, aby silniej przekonać zbieracza śmieci do uruchomienia? Używamy 1.7.0_09-icedtea i używamy Parallel GC. Chciałbym albo (a) niezawodny sposób ręcznego wymuszenia zbierania śmieci, albo (b) jakiś sposób dostrojenia kolektora, tak aby podejmował bardziej inteligentną automatyczną decyzję. (b) wydaje się trudne, ponieważ nie jest dla mnie jasne, w jaki sposób kolektor może wykryć, że nasz zestaw roboczy zmienia się w ten dramatyczny sposób.
Jestem gotów uciekać się do znacznej hackery, jeśli zajdzie taka potrzeba; jest to dla nas poważny problem. (Możemy spojrzeć na kompaktory CMS lub G1 jako alternatywy, ale jestem podejrzliwy co do wpływu przepustowości CMS, a G1 jest uważany za słabo zachowujący się wobec dużych tablic bajtów, których używamy.)
uzupełnienie: W produkcji nasze dotychczasowe doświadczenie polegało na tym, że System.gc ()zazwyczaj nie uruchamia pełnego czyszczenia pamięci; przynajmniej w sytuacjach, w których to nazywamy. (Wywołujemy go tylko raz na 10 do 30 minut, ze stertą nieco, ale nie do końca wypełnioną śmieciami). Byłoby miło, gdyby można było wyzwolić zbieranie śmieci w bardziej niezawodny sposób, ale to pomaga nam przez większość czasu.