Garbage collector G1 i UseStringDeduplication

Garbage collector G1 i UseStringDeduplication
RequiredNickname
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 646
0

Pewnego spokojnego lipcowego wieczoru roku pańskiego 2024 czytając wieczorem w łóżku na ipadzie, przy świetle siec z promieniami zachodzącego słońca leniwie przebijającego się przez moje rolety noc-dzień na taflę mojego niewielkiego budżetowego tv w sypialni, na temat różnych garbage collectorów w jvm trafiłem na informację jakoby G1 posiadał opcję skonfigurowania mechanizmu służącego deduplikacji stringów na heapie (XX:+UseG1GC -XX:+UseStringDeduplication).

Cytując klasyka zacząłem się zastanawiać...
screenshot-20240803152522.png

Naturalnie, idąc z duchem czasu zaprzęgłem do roboty chat gpt (w wersji premium plus pro 5g) i zapytałem w jakich wypadkach stringi mogą znaleźć się na heap poza string poolem skoro nikt normalny nie tworzy w aplikacji z palca stringów poprzez new.

W odpowiedzi dostałem:

  1. Deserializacja obiektów:
    • Gdy obiekty typu String są deserializowane z wejścia/wyjścia, nie są automatycznie dodawane do String Pool.
    2. Podział na podłańcuchy (substring):
    • Gdy tworzone są podłańcuchy z istniejącego Stringa, mogą one czasami trafić bezpośrednio na heap, zwłaszcza w przypadku wersji JVM nowszych niż 1.7, gdzie zmieniła się implementacja klasy String.
    3. Dynamiczne generowanie Stringów:
    • Kiedy Stringi są generowane dynamicznie, na przykład przez konwersję z innych typów danych (np. String.valueOf(int)), nie zawsze trafiają one do String Pool.
    4. Interakcje z zewnętrznymi bibliotekami:
    • Gdy Stringi są generowane przez zewnętrzne biblioteki lub frameworki, mogą być tworzone na heapie.
    5. Manipulacja przez API:
    • Korzystanie z niektórych metod API jak StringBuilder lub StringBuffer, które są używane do dynamicznej modyfikacji i tworzenia Stringów, może spowodować, że wynikowy String znajdzie się na heapie.

i teraz przychodzę z pytanime do szanownych starszych i mądrzejszych kolegów czy ta odpowiedź jest poprawna?
A jeżeli tak to czy ktoś sprawdzał kiedyś jakie efekty daje włączenie tego mechanizmu deduplikacji?
No bo rozumiem, że skoro są to obiekty na heapie jak każde inne to GC nie ma dla nich litości i gdy wykryje, że nie ma do nich referencji (lub jest ale cykliczna) to wywali je w diabły.

Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
2
RequiredNickname napisał(a):

(...)
i teraz przychodzę z pytanime do szanownych starszych i mądrzejszych kolegów czy ta odpowiedź jest poprawna?

ogólnie tak. dla przykładu, nasz system parsuje kontrakty (trade'y) w postaci xml i takich wiadomości obrabiamy mnóstwo, w związku z czym w pamięci jest zduplikowane dużo stringów. dla przykładu, jeśli klient przyśle 100 trejdów i wszystkie parsujemy i wrzucamy do cache'a to wiele wartości (stringów wyciętych z oryginalnych xmli) będzie co najmniej 100x zduplikowanych.

A jeżeli tak to czy ktoś sprawdzał kiedyś jakie efekty daje włączenie tego mechanizmu deduplikacji?

zmniejsza zużycie sterty odpowiednio do ilości zduplikowanych stringów. konkretne dane możesz uzyskać włączając wypisywanie statystyk:
https://stackoverflow.com/questions/46537415/is-string-deduplication-feature-of-the-g1-garbage-collector-enabled-by-default

java -Xmx256m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics jvm.StringDeDuplicationTester
(...)
With JEP 158:Unified JVM Logging implementation in Java9, the garbage collector flags are marked as legacy and alternate way of tracing them is using -Xlog feature. A detailed list of the replacement for converting GC Logging Flags to Xlog is listed here. One of which suggests replacing:
PrintStringDeduplicationStatistics => -Xlog:stringdedup*=debug

zależy od tego jaką jvmę odpalasz, przełączniki mogą być różne.

No bo rozumiem, że skoro są to obiekty na heapie jak każde inne to GC nie ma dla nich litości i gdy wykryje, że nie ma do nich referencji (lub jest ale cykliczna) to wywali je w diabły.

tu nie chodzi o nieosiągalne obiekty (tzn. bez dochodzących referencji), ale o zduplikowane. to dwie zupełnie różne rzeczy. jeśli np. powiesz użytkownikowi, żeby podał nazwę bohaterów w grze i ten poda kilka razy to samo imię, to te stringi nie będą z automatu zdeduplikowane.

deduplikacja stringów w javie polega konkretnie na deduplikacji tablicy bajtów czy tam charów, która jest używana wewnątrz stringa. sam obiekt klasy string nie jest deduplikowany, ponieważ ma swoją tożsamość (i tego deduplikacja nie zmienia) - można go porównywać operatorem == (do sprawdzania czy mamy do czynienia z dokładnie tym samym obiektem), synchronizować się na nim itp itd. ta tablica bajtów (vel charów) w środku stringa to szczegół implementacyjny i java może z nią robić co chce, dopóki sam obiekt klasy string zachowuje się tak jak zostało to zdefiniowane w dokumentacji (kontrakcie).

dlaczego deduplikacja nie jest domyślnie włączona tylko wymaga włączenia? bo kosztuje, zarówno pamięć jak i czas procesora, a zyski zależą od tego jak dużo jest zduplikowanych stringów.

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2384
2

A jeżeli tak to czy ktoś sprawdzał kiedyś jakie efekty daje włączenie tego mechanizmu deduplikacji?

Tak. Można to zrobić via analiza heap dumpa z poziomu JMC. Efekt deduplikacji będzie powiązany z Twoim workloadem. W moim przypadku workload to XMLe od kilkunastu kB do kilkuset GB, w których pojawia się wielokrotnie ten sam string (np. identyfikator klienta, czy data, nazwa miasta itd.). Poglądowo, dla tego samego workloadu statystyki bez deduplikacji i z deduplikacją (ręczną, przez wywołanie intern() na stringu).

Bez deduplikacji:

screenshot-20240803160535.png

Z deduplikacją:

screenshot-20240803160759.png

RequiredNickname
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 646
0

Dzięki za rozjaśnienie.

Wrzucam ciekawy artykuł dla potomnych:
https://dzone.com/articles/usestringdeduplication

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.