Cóż, w jednym jest kilka pytań!
1 - Jak zarządza się obiektami krótkotrwałymi?
Jak wspomniano wcześniej, JVM doskonale radzi sobie z ogromną ilością obiektów krótkotrwałych, ponieważ opiera się na hipotezie słabego pokolenia .
Zwróć uwagę, że mówimy o obiektach, które dotarły do pamięci głównej (sterty). Nie zawsze tak jest. Wiele tworzonych obiektów nie opuszcza nawet rejestru procesora. Na przykład rozważmy tę pętlę for
for(int i=0, i<max, i++) {
// stuff that implies i
}
Nie myślmy o rozwijaniu pętli (optymalizacjach, które JVM wykonuje w dużym stopniu w kodzie). Jeśli max
jest równe Integer.MAX_VALUE
, wykonanie pętli może zająć trochę czasu. Jednak i
zmienna nigdy nie ucieknie z bloku pętli. Dlatego JVM umieści tę zmienną w rejestrze procesora, regularnie ją zwiększając, ale nigdy nie wyśle jej z powrotem do pamięci głównej.
Zatem tworzenie milionów obiektów nie jest wielkim problemem, jeśli są używane tylko lokalnie. Będą martwe, zanim zostaną przechowane w Edenie, więc GC nawet ich nie zauważy.
2 - Czy warto zmniejszyć narzut GC?
Jak zwykle to zależy.
Najpierw należy włączyć rejestrowanie GC, aby mieć jasny obraz tego, co się dzieje. Możesz to włączyć za pomocą -Xloggc:gc.log -XX:+PrintGCDetails
.
Jeśli Twoja aplikacja spędza dużo czasu w cyklu GC, to tak, dostrój GC, w przeciwnym razie może to nie być tego warte.
Na przykład, jeśli masz młody GC co 100 ms, który zajmuje 10 ms, spędzasz 10% swojego czasu w GC i masz 10 kolekcji na sekundę (co jest huuuuug). W takim przypadku nie spędzałbym czasu na strojeniu GC, ponieważ te 10 GC / s nadal by tam były.
3 - Trochę doświadczenia
Podobny problem miałem na aplikacji, która tworzyła ogromną ilość danej klasy. W logach GC zauważyłem, że szybkość tworzenia aplikacji wynosiła około 3 GB / s, czyli zdecydowanie za dużo (no dalej ... 3 gigabajty danych na sekundę?!).
Problem: zbyt wiele częstych GC spowodowanych tworzeniem zbyt wielu obiektów.
W moim przypadku założyłem profiler pamięci i zauważyłem, że klasa reprezentowała ogromny procent wszystkich moich obiektów. Prześledziłem instancje, aby dowiedzieć się, że ta klasa była w zasadzie parą wartości logicznych opakowanych w obiekt. W takim przypadku dostępne były dwa rozwiązania:
Przerób algorytm, aby nie zwracać pary wartości logicznych, ale zamiast tego mam dwie metody, które zwracają każdą wartość logiczną osobno
Buforuj obiekty, wiedząc, że były tylko 4 różne instancje
Wybrałem drugą, ponieważ miała najmniejszy wpływ na aplikację i była łatwa do wprowadzenia. Umieszczenie fabryki z niezabezpieczoną wątkowo pamięcią podręczną zajęło mi kilka minut (nie potrzebowałem zabezpieczenia wątków, ponieważ ostatecznie miałbym tylko 4 różne instancje).
Współczynnik alokacji spadł do 1 GB / s, podobnie jak częstotliwość młodych GC (podzielona przez 3).
Mam nadzieję, że to pomoże!