Java Container Toepassingsgeheugenanalyse

Voor containertoepassingen is het moeilijk om problemen te vinden die veroorzaakt worden door geheugenoverschrijding. Als het gebruik de geheugengrens van de container overschrijdt, kan een toepassing stilzwijgend falen zonder enig spoor achter te laten.

In dit artikel ga ik enkele technieken behandelen die kunnen worden gebruikt om de oorzaak van geheugengebruik in een Java containertoepassing te identificeren.

Geheugentype

In een typische Java-toepassing, geheugen kan ruwweg worden verdeeld in heap en niet-heap. Heapgeheugen kan worden ingesteld door relevante JVM-parameters op te geven bij het starten van elke Java-toepassing.

Niet-heapgeheugen bestaat uit native geheugen dat wordt gebruikt door de JVM zelf of door elke bibliotheek die binnen de toepassing wordt gebruikt met JNI (Java Native Interface).

Methode

Voor heapgeheugen kan een heapdump worden genomen en geanalyseerd met behulp van heapdumpanalysegereedschappen. Een van de beste tools voor heapdumpanalyse is eclipse MAT.

Java biedt een mechanisme om native geheugentoewijzing te volgen door native memory tracking in te schakelen, maar het kan mogelijk niet alle geheugen weergeven dat door native bibliotheken is toegewezen.

Jemalloc is een utility die kan worden gebruikt om geheugen dat is toegewezen door native bibliotheken te volgen. Native geheugen wordt toegewezen met behulp van een standaard geheugen toewijzer genaamd malloc. Jemalloc is een algemeen-doel malloc implementatie waarmee geheugen toewijzingstracking kan worden ingeschakeld. Het volgt alle native geheugentoewijzing en genereert heap profieldumps.

Deze heap profielen kunnen vervolgens worden geanalyseerd met behulp van Jeprof utility. Jeprof genereert de heap toewijzingsrapportage, waarbij het geheugen dat wordt gebruikt door functies in de applicatie wordt gemarkeerd.

Analyse

Hieronder is een geheugenanalyse van een voorbeeld container Java applicatie. De applicatie laadt een voorbeeld Tensorflow model om native geheugenbenutting te activeren en draait in een Docker container.

Hieronder is de Docker geheugengebruik. Het toont 254MB. Laten we proberen de bron van het geheugengebruik te pinpointen.

Totaal Geheugen

Om een idee te krijgen van het totale geheugen dat wordt gebruikt door de applicatieproces, kunnen we Resident Set Size (RSS) controleren. Het is het totale geleverde geheugen dat in de hoofdgeheugen of RAM aanwezig is. Er zijn meerdere utilities die hierbij kunnen helpen, zoals top, ps of pmap.

Controleren op RSS helpt niet om de oorspronkelijke bron van het gebruik te pinpointen. Voor de voorbeeldapplicatie, met behulp van de onderstaande opdracht, is de totale RSS 376MB.

Shell

 

ps --no-header -o rss $(pidof java)

Heap-analyse

Hieronder is de heapgeheugengebruik weergegeven zoals gegenereerd door het eclipse MAT-hulpmiddel. Het totale behouden heap is weergegeven als 2,2MB, wat ver onder het totale geheugengebruik ligt zoals weergegeven door Docker en aangeeft dat het merendeel van het verbruik afkomstig is van het niet-heapgebied.

Native Memory-analyse

Na het bekijken van het overzicht van native geheugen met behulp van de onderstaande opdracht, lijkt het totale geheugengebruik ongeveer 99MB te zijn. Dit waarde is echter lager dan het totale geheugengebruik en identificeert niet nauwkeurig de oorzaak van het probleem.

Shell

 

jcmd $(pidof java) VM.native_memory \
    | grep -P "Total.*committed=" \
    | grep -o -P "(?<=committed=)[0-9]+(?=KB)"

Off-Heap Memory-analyse

Een analyse met Jemalloc en Jeprof toont aan dat native geheugengebruik voornamelijk wordt toegeschreven aan de Tensorflow-bibliotheek, met een totale consumptie van ongeveer 112MB.

Deze inzichten geven een duidelijk aanwijzing over de bron van native geheugengebruik en kunnen verder worden onderzocht om eventuele overmatige consumptie te minimaliseren.

Conclusie

Java-geheugenanalyse is cruciaal, met name voor toepassingen op basis van containers. Weten waar het geheugengebruik in een toepassing vandaan komt, kan ons helpen de geheugenvereisten te begrijpen en applicatiekosten te verlagen door onnodige consumptie te verwijderen.

Bij het controleren op geheugengebruik moeten alle soorten geheugen en hun bronnen worden gepinpoint. Heap dump-analyse kan bronnen van heapgeheugengebruik pinpointen, en Jemalloc en Jeprof zijn handig bij het pinpointen van bronnen van native geheugengebruik.

Sample Application Code Link

https://github.com/parveensaini/JavaContainerMemoryAnalysis

Source:
https://dzone.com/articles/java-container-application-memory-analysis