System.gc () vs przycisk GC w JVisualVM / JConsole

Obecnie testuję mój prototyp dowodu koncepcyjnego dotyczący schematu XML i zbudowałem go wokół bardzo zajmującej pamięć zewnętrznej biblioteki dla automatów drzewnych (dla których mam źródła), chciałbym narysować „prawdziwy szczyt” (sterty ) Zużycie pamięci w różnych przebiegach z rosnącymi rozmiarami schematu (zastosowana metryka pasuje do mojego celu i nie wpływa na pytanie), lub przynajmniej rozsądne jej przybliżenie.

Aby dać rząd wielkości, dla przebiegu z rzeczywistym szczytem 100 MB (testowałem go działając kilka razy dokładnie w tej samej konfiguracji wejść / parametrów, wymuszając pamięć jvm z -Xmx i -Xms na malejącą wartość, otrzymujęWyjątek w wątku „main” java.lang.OutOfMemoryError: przekroczono limit narzutów GC <100 MB, ze stabilnymi i powtarzalnymi wynikami) zajmuje około 1,1 GB, dlatego niezwykle ważne jest dla mnie uzyskanie rzeczywistej liczby, ponieważ bardzo się one różnią!

Ostatnie 10 dni spędziłem czytając pytania w internecie i przeglądając stosy, a tak naprawdę wiem:

System.gc () „sugeruje” uruchomienie GC, nie wymusza go w żaden sposób, więc nie można polegać na nim do wykrywania szczytów użycia pamięci

Zazwyczaj sugeruje się policzenie zawodu obiektu (widziałemRozmiar projekt dla tego, próbowałem i działa dobrze, nawet jeśli nie pasuje do moich potrzeb), nie jest to dla mnie wykonalne, ponieważ przydział dużej ilości pamięci odbywa się z powodu tworzenia wielu iteratorów kolekcji (zestawów, list i map) w różnych metody, nazywane bardzo dużą liczbą razy (powiedzmy miliony za 10 minut za to, co pamiętam), więc byłoby bardzo trudno wykryć wszystkie zaangażowane obiekty i wykonać sumy (debugowałem wiele wielu uruchomień w ciągu dni wykresy zużycia pamięci bez możliwości zidentyfikowania tylko jednej szyjki butelki

Nie ma możliwości łatwego uzyskania zajętości pamięci metody (wyrażonej jako szczyt alokacji pamięci obiektu)

Faktem jest, że sam doświadczyłem, że wywołania System.gc () nie są wiarygodne (np. Różne przebiegi tej samej konfiguracji, inna pamięć odczytana po System.gc () z powodu wywołania GC lub nie), ale kiedy Naciskam przycisk „GC” w JVisualVM lub Jconsole itnigdy nie uruchamia GC lub odmawia.

Moje pytanie brzmi: wywołanie ich implementacji (nie próbowałem jeszcze, ale z tego, co przeczytałem do tej pory, wydaje się to możliwe przy użyciu jconsole.jar zdołączyć api) różni się od wywołania System.gc () bezpośrednio z mojego kodu, rozwiązując w ten sposób mój problem? Jeśli nie, jak wytłumaczysz „zachowanie deterministyczne” tego przycisku?

Do tej pory przeprowadziłem ręczny test rzeczywistego piku pamięci przy 10 rosnących rozmiarach schematu (dla tego rodzaju pomiarów schematy są automatycznie generowane z pojedynczego „parametru złożoności”) i wykreśliłem oczekiwaną krzywą, jeśli nie będę w stanie uzyskać lepsze rozwiązanie Chcę uruchomić mój kod jako zewnętrzny słoik z opcją -Xmx / -Xms równą nieco mniejszej niż przewidywana oczekiwana wartość szczytowa pamięci, przechwycenie wyjątku OutMemoryException w zewnętrznym procesie ErrorStream i ponowne uruchomienie ze zwiększoną pamięcią do pełnego uruchomienia jest osiągnięte. (Jeśli przewidywanie naiwnej pamięci nie będzie wystarczająco solidne, zastosuję odpowiednie techniki uczenia maszynowego). Wiem, że nie jest to eleganckie rozwiązanie, ale w moim scenariuszu (akademickim) mogę pozwolić sobie na poświęcenie dodatkowego czasu na te pomiary. Jeśli masz inne sugestie lub ulepszenia tej brutalnej metody, jesteś (bardzo) mile widziany, aby się nimi podzielić.

Informacje o systemie (maszyna to Fedora 17, 64 bit):

java wersja "1.7.0_04" Java (TM) SE Runtime Environment (kompilacja 1.7.0_04-b20) Java HotSpot (TM) 64-bitowy serwer VM (kompilacja 23.0-b21, tryb mieszany)

Z góry dziękuję, Alessandro

questionAnswers(4)

yourAnswerToTheQuestion