Pytanie Wykorzystanie pamięci Java w systemie Linux


Mam na głowie garść serwerów aplikacji Java, na których zainstalowane są najnowsze wersje Tomcat 6 i Sun 6 Java na szczycie systemu CentOS 5.5 Linux. Każdy serwer uruchamia wiele instancji Tomcat.

Ustawiam parametry -Xmx450m -XX: MaxPermSize = 192m, aby kontrolować, jak duże będą sterty i permeny. Te ustawienia dotyczą wszystkich instancji Tomcat na wszystkich serwerach aplikacji Java, łącznie około 70 instancji Tomcat.

Oto typowe użycie pamięci jednej z tych instancji Tomcata zgłoszonej przez sondę Psi

Eden           = 13M
Survivor       = 1.5M 
Perm Gen       = 122M 
Code Cache     = 19M 
Old Gen        = 390M 
Total          = 537M

CentOS jednak raportuje użycie pamięci RAM dla tego konkretnego procesu na 707M (według RSS), z którego pozostało 170M pamięci RAM.

Zdaję sobie sprawę, że sama JVM i niektóre jej biblioteki zależności muszą być załadowane do pamięci, więc zdecydowałem się wystrzelić PMap -d, aby znaleźć ich ślad pamięci. Według moich obliczeń stanowi to około 17 milionów.

Następnie jest stos wątków Java, który wynosi 320k na wątek w 32-bitowej maszynie JVM dla systemu Linux. Ponownie używam sondy Psi, aby policzyć liczbę wątków na danej maszynie JVM, a łączna liczba wątków wynosi 129. Więc 129 + 320k = 42M

Czytałem, że NIO wykorzystuje pamięć poza stosem, ale nie używamy NIO w naszych aplikacjach.

Więc tutaj obliczyłem wszystko, co przychodzi do (mojego) umysłu. I uwzględniłem tylko 60M "brakującego" 170M.

czego mi brakuje?


12
2017-09-05 15:00


pochodzenie


Sam zadawałem to samo pytanie. Odkryłem, że mamy kilka stron anonowych (zwróconych przez PMap) o rozmiarach od 65536k do 65508k. Nie jestem pewien, co to jest, ale stanowią one około jednej trzeciej naszego zużycia pamięci. - sehugg


Odpowiedzi:


Spróbuj skorzystać z inkrementującego się garbage collectera, używając opcji wiersza poleceń -Xincgc. Jest trochę bardziej agresywny w całym wysiłku GC i ma specjalną szczęśliwą anomalię: w rzeczywistości oddaje część nieużywanej pamięci systemowi operacyjnemu, w przeciwieństwie do domyślnych i innych opcji GC! To sprawia, że ​​JVM zużywa o wiele mniej pamięci, co jest szczególnie dobre, jeśli używasz wielu maszyn JVM na jednym komputerze. Kosztem pewnej wydajności - ale możesz tego nie zauważyć. Incgc jest małym sekretem, jak się wydaje, ponieważ nikt go nigdy nie przywołuje ... Był tam przez eony (nawet 90 lat).


3
2017-09-08 19:20





Arnar, w procesie inicjowania maszyny JVM JVM przydzieli pamięć (mmap lub malloc) o rozmiarze określonym przez -Xmx i MaxPermSize, tak więc JVM przeznaczy 450+ 192 = 642m przestrzeni sterty dla aplikacji na początku procesu JVM. Tak więc przestrzeń java dla aplikacji nie jest 537 ale jej 642m.So teraz, jeśli wykonasz obliczenia, to dostaniesz brakującą pamięć. Mam nadzieję, że to pomaga.


2
2017-09-05 15:27



Myślę, że możesz ustawić początkową stertę za pomocą przełącznika Xms, a zwiększy się do rozmiaru Xmx tylko na żądanie. - duduamar
Tak, początkowo aplikacja otrzyma rozmiar równy -Xms, aby przydzielić obiekt, i dalej rośnie do -Xmx zgodnie z wymaganiami aplikacji. Jednak sterty JVM to ciągła przestrzeń o rozmiarze -Xms + wielkość Perm. Gdy kupa rośnie, otrzyma trochę więcej pamięci z tej wstępnie przydzielonej przestrzeni o rozmiarze -Xmx. - Anil Vishnoi
-Xms to jeden parametr, który pomoże JVM zdecydować kiedy wyzwolić GC, więc gdy aplikacja całkowicie zajmie stertę wielkości -Xms, JVM uruchomi GC i spróbuje posprzątać śmieciami, potem GC nie zrobił tego t wyczyściło dużo miejsca, aby przydzielić żądanie obiektu aplikacji, a następnie JVM rozszerzy stertę o określoną kwotę. (Zmniejszenie i ekspansja są oparte również na zbyt wielu innych czynnikach). - Anil Vishnoi
Dziękuję za odpowiedź Anil. Właśnie zrestartowałem maszynę JVM, a po jej w pełni uśrednionym, ślad RSS zajmuje tylko 273M. Stawka JVM + permgen + pamięć podręczna kodu + natywny rozmiar kodu + stos wątków wynosi obecnie 248M. Więc nie sądzę, że cała sterta jest przydzielana do pamięci RSS. Jeśli nie podam opcji -Xms lub -XX: PermSize JVM ustawia -xms na 64mb (1/64 dostępnej pamięci RAM, czyli 4G) i XX: PermSize na 64mb. - Arnar Gunnarsson
-Xmx jest przydzielany z góry, ponieważ JVM wymaga bloku sąsiadującej przestrzeni adresowej. Ale to nie znaczy, że cała pamięć zostanie użyta. W systemie Linux zostanie oznaczony jako nieaktywny i nie będzie rezydentny. Dlatego Twój RSS (Resident Set Size) może być niższy. - Vincent Robert


Java przydziela tyle pamięci wirtualnej, ile może potrzebować z góry, jednak strona rezydentna będzie tym, ile faktycznie używasz. Uwaga: wiele bibliotek i wątków ma swoje własne nadwyżki, a jeśli nie korzystasz z pamięci bezpośredniej, nie oznacza to, że żaden z systemów bazowych tego nie robi. na przykład jeśli użyjesz NIO, użyje pewnej bezpośredniej pamięci, nawet jeśli użyjesz Bajty Bajty.

Wreszcie, 100 MB jest warte około 8 £. Być może nie warto spędzać zbyt wiele czasu na martwieniu się o to.


1
2017-09-05 17:00



Peter, mam około 70 instancji Tomcat na wielu serwerach aplikacji. Ta liczba naprawdę się sumuje. - Arnar Gunnarsson
Jak więc wdrożyć nowe aplikacje i wycofać je / usunąć je niezależnie. Skutecznie używasz płaskiego pliku będącego własnością root / systemu jako bazy danych bez obsługi transakcji lub niezależnych operacji. IMHO Im więcej masz usług, tym gorsze jest dla mnie rozwiązanie. Jeśli masz wiele skrzynek, szanse na to, że system nie wdroży się prawidłowo, muszą stanowić problem. - Peter Lawrey


Nie jest to bezpośrednia odpowiedź, ale rozważałeś także hosting wiele witryn w tej samej instancji Tomcat? Może to zaoszczędzić trochę pamięci kosztem dodatkowej konfiguracji.


0
2017-09-06 23:51





Arnar, JVM, używa także wszystkich plików JAR mmap, które będą używać NIO i przyczynią się do RSS. Nie wierzę, że są one uwzględnione w żadnym z twoich pomiarów powyżej. Czy przypadkiem masz znaczną liczbę dużych plików jar? Jeśli tak, strony używane do tych mogą być twoją brakującą pamięcią.


0
2017-09-09 03:48