Eclipse Memory Analyzer MAJUG November 2008

44
1

Transcript of Eclipse Memory Analyzer MAJUG November 2008

Page 1: Eclipse Memory Analyzer MAJUG November 2008

1

Page 2: Eclipse Memory Analyzer MAJUG November 2008

2

Page 3: Eclipse Memory Analyzer MAJUG November 2008

3

Page 4: Eclipse Memory Analyzer MAJUG November 2008

4

Ein Garbage Collector sorgt dafür dass nur die Objekte dir noch erreichbar sind im Speicher bleiben.Nicht erreichbare Objekte können dem Programm nicht mehr von Nutzen sein und können dahergelöscht werden.

Wann der GC Objekte löscht ist typischerweise nicht determiniert. Dies steht im Gegensatz zuReference Counting, dass z.B. in C++ gerne als einfache automatische Speicherverwaltung genutztwird.

Page 5: Eclipse Memory Analyzer MAJUG November 2008

5

Malloc muss normalerweise eine Liste freier Speicherbereiche verwalten ->Malloc typischerweiselangsamer als ein new in Java

Page 6: Eclipse Memory Analyzer MAJUG November 2008

6

Das eigentliche Problem sind die versteckten Kosten des GC.

Praktisch jede GC Implementierung erfordert eine „stop the world“ Phase, bei der alleApplikationsthreads angehalten werden müssen.

Der Benutzer hat dann den Eindruck einer nicht vorhersagbaren Antwortzeit.

Page 7: Eclipse Memory Analyzer MAJUG November 2008

7

„Normaler“ Garbage Collector log

http://www.tagtraum.com/gcviewer.html

Der Speicherverbrauchstrend zeigt keinen Anstieg. Daher liegt hier wohl kein Memory Leak vor

Je kleiner der Speicherverbrauch nach einem Full GC ist desto weniger Full GC‘s müssen bei sonstgleichen Bedinungen ausgeführt werden

Page 8: Eclipse Memory Analyzer MAJUG November 2008

8

Page 9: Eclipse Memory Analyzer MAJUG November 2008

9

Shallow size == flache Grösse des Objektes. Die Shallow Size ist in der Praxis ein nützliches Maß fürden Overhead eines Objektes.

„object header“ : Jedes Java Object (in der SUN/SAP JVM) hat einen Header, der Informationen überdas Object Layout, Type, GC Zustand, Synchronization Status, und identity hash code enthält. DerObject header ist 2 Worte (8Bytes unter 32 bit) groß.

Page 10: Eclipse Memory Analyzer MAJUG November 2008

10

Man beachte :

Mehrere Stringobjekte können das gleiche char[] verwenden (sharing)

Selbst ein leerer String braucht mehr als 24 bytes wenn das leere char[] nicht gemeinsam verwendetwird.

Page 11: Eclipse Memory Analyzer MAJUG November 2008

11

Diese Werte beziehen sich auf eine SUN JVM für 32 bit Intel Prozessoren. Bei anderen JVM‘s oderanderen Prozessoren kann der Speicherverbrauch anders aussehen.

Page 12: Eclipse Memory Analyzer MAJUG November 2008

12

Unter 64 bit braucht eine Java Applikation signifikant mehr Speicher als unter 32 bit, weil Referenzen8 Byte statt 4 Byte benötigen. Der Unterschied im Speicherverbrauch hängt daher vor allem davon abwieviele Referenzen es gibt.

Bei identischer Hardware (Speichergröße) bringt der Übergang auf 64 bit daher zunächst oft keinenPerformancegewinn. Allerdings ist unter 32 Bit Windows die maximale Größe des Java Heaps aufnicht viel mehr als 1 Gbyte beschränkt (etwas mehr unter Linux und bis zu 3,8 Gbyte unter Solaris).

Page 13: Eclipse Memory Analyzer MAJUG November 2008

13

In diesem vereinfachten Beispiel können folgende Schlüsse aus den Daten gezogen werden :

Es wird am meisten Speicher in char[] verbraucht

Die Anzahl der String Objekte ist etwas kleiner als die der char[]. Es wird aus den Daten nicht klar obdie vielen String Objekte char[] „sharen

Es ist nicht klar ob möglicherweise com.erp.Order viele Stringobjekte referenziert und dadurchletztlich den hohen Speicherverbrauch verursacht

Page 14: Eclipse Memory Analyzer MAJUG November 2008

14

Da die shallow size in der Praxis nicht sehr nützlich ist, braucht man ein Maß für die Menge desSpeichers die festgehalten wird.

Dazu simuliert man einen GC Lauf unter der Annahme, das eine bestimme Menge von Objekten nichtmehr existieren würde.

Page 15: Eclipse Memory Analyzer MAJUG November 2008

15

Hier ist ein Beispiel der LinkedList Klasse aus dem JDK dargestellt

Page 16: Eclipse Memory Analyzer MAJUG November 2008

16

Page 17: Eclipse Memory Analyzer MAJUG November 2008

17

Page 18: Eclipse Memory Analyzer MAJUG November 2008

18

Ein Heap Dump ist ein File, dass alle „noch lebendenden“ Java Objekte zu einem bestimmtenZeitpunkt enthält.

„Noch lebenden“= Erreichbar

Genaugenommen kann ein Heap dump auch noch Objekte enthalten, die nicht mehr referenziertwerden. Im Allgemeinen werden diese Objekte von den gängigen Heap dump Analyse Toolsallerdings nicht betrachtet.

Vor einem Heap dump wird ein Full GC ausgelöst.

Page 19: Eclipse Memory Analyzer MAJUG November 2008

19

Dies gilt zumindest für die SUN/SAP JVM.

Andere JVM‘S (IBM) schreiben Heap Dumps, die einige Informationen nicht enthalten

Page 20: Eclipse Memory Analyzer MAJUG November 2008

20

Es gibt einige verschiedene Möglichkeiten einen Heap dump zu erzeugen

Page 21: Eclipse Memory Analyzer MAJUG November 2008

21

Die Option

Page 22: Eclipse Memory Analyzer MAJUG November 2008

22

Page 23: Eclipse Memory Analyzer MAJUG November 2008

23

Das IBM Heap Dump Format wird durch ein zusätzliches Plugin unterstützt

MAT kann sowohl standalone als auch innerhalb von Eclipse benutzt werden

Page 24: Eclipse Memory Analyzer MAJUG November 2008

24

Wichtige Funktionen

Class histogramm

Show object

Retained size

Retained set

Page 25: Eclipse Memory Analyzer MAJUG November 2008

25

Page 26: Eclipse Memory Analyzer MAJUG November 2008

26

Objekte mit großer retained Size in einem großen Heap Dump mit Millionen von Objekten zu findenist manuell sehr schwierig.

Ein naiver Algorithmus um die größten Objekte zu finden,könnte für jedes Objekt im Heap eineSimulation einer Garbage Collection durchführen. Dies würde allerdings O(n^2) Aufwand bedeuten.Nimmt man z.B. 5 Sekunden für eine GC Simulation an und hat einen Heap mit 10 MillionenObjekten so bräuchte man mit diesem Algorithmus schon mehr als 1,5 Jahre. Außerdem hätte mandamit noch nicht die Information über die immediate Dominatoren der Objekte.

Der durch die immediate Dominatoren aufgespannte „Dominator tree“ erlaubt es unter anderem dieretained Size aller Objekte vorzuberechnen und der Größe nach zu sortieren.

Der Dominator Tree kann in „fast“ O(n) (O(m*agr;(m, n); agr == Inversion der Ackermannfunktion) Zeitmit dem Lengauer Tarjan Algorithmus (http://portal.acm.org/citation.cfm?id=357071&dl=GUIDE,)berechnet werden.

Page 27: Eclipse Memory Analyzer MAJUG November 2008

27

Das Business Objekt vom Typ com.myerp.buyer.Order referenziert einen LinkedList die StringObjekte enthält.

LinkedList$Entry2 ist der immediate Dominator von String 2

Page 28: Eclipse Memory Analyzer MAJUG November 2008

28

Der Immediate Dominator von LinkedList$Entry2 ist LinkedList$Entry0.

LinkedList$Entry1 ist kein Dominator von LinkedList$Entry2, da beim Entfernen vonLinkedList$Entry 1 weiterhin eine Referenz von

LinkedList$Entry0 auf LinkedList$Entry 2 besteht.

Page 29: Eclipse Memory Analyzer MAJUG November 2008

29

Durch die immediate Dominator‘s wird ein Baum aufgespannt (== Dominator tree).

Page 30: Eclipse Memory Analyzer MAJUG November 2008

30

Das com.myerp.buyer.Order Objekt „domiert die 3 String Objekte. Das heißt, dass wenn man dieseObjekt aus dem Speicher entfernen würde dann würde der GC auch die 3 Strings freigeben. Daß sichdazwischen eine Java Collection Klasse befindet ist für die Analyse meist nicht von Interesse. Es kanndaher nützlich sein im Dominator Tree Knoten herauszufiltern. Typischerweise möchte man Instanzenvon Java Standard library Klassen herausfiltern.

Page 31: Eclipse Memory Analyzer MAJUG November 2008

31

Wichtige Funktionen

Dominator Tree

Immediate Dominators

Top Consumers

Page 32: Eclipse Memory Analyzer MAJUG November 2008

32

Page 33: Eclipse Memory Analyzer MAJUG November 2008

33

Im Eclipse Debugger kann man dies leicht nachvollziehen. Der Grund für dieses Verhalten istdie effiziente Implementierung von StringBuffer.toString(). Diese kopiert nämlich das internechar[] des StringBuffer‘s nicht sondern verwendet es für den neu erzeugten String (unter JDK1.4).

Page 34: Eclipse Memory Analyzer MAJUG November 2008

34

Im Eclipse Debugger kann man dies leicht nachvollziehen. Der Grund für dieses Verhalten istdie effiziente Implementierung von StringBuffer.toString(). Diese kopiert nämlich das internechar[] des StringBuffer‘s nicht sondern verwendet es für den neu erzeugten String (unter JDK1.4).

Page 35: Eclipse Memory Analyzer MAJUG November 2008

35

Dieses Verhalten ist so gewollt. Der Vorteil ist dass mehrere String Objekte sich ein char[]teilen können.

Page 36: Eclipse Memory Analyzer MAJUG November 2008

36

Page 37: Eclipse Memory Analyzer MAJUG November 2008

37

XML DOM Bäume brauchen sehr viel Speicher, und sollten daher nicht direkt alsDatenstruktur verwendet werden.

Wenn der XML Parser alte Daten referenziert wird unnötig Speicher verbraucht.

XSLT Transformerobjekte können mehrere Mbyte verbrauchen. Da die Transformerobjekterelativ teuer zu erzeugen sind kann man durch Pooling versuchen immer nur einen begrenzteZahl im Speicher zu halten.

Page 38: Eclipse Memory Analyzer MAJUG November 2008

38

Caches sind relativ aufwendig zu implementieren, da nicht nur der Cache selberimplementiert werden muss sonder auch die Infrastruktur zum Monitoring und zurAdministration. Daher sollte man auf eine existierende stabile Cacheimplementierungzurückgreifen.

Ist eine Webseite „stateless“, kann also der Inhalt der Seite nur aus den Parametern desRequest berechnet werden, so kann sie auch gut vom Browser gecached werden.

Page 39: Eclipse Memory Analyzer MAJUG November 2008

39

Es gibt einige Strategien zur Minimierung des Speicherverbrauchs. Hier nur die wichtigsten.

Der Memory Analyzer bietet z.B. Queries für das finden leerer Collections an.

Page 40: Eclipse Memory Analyzer MAJUG November 2008

40

Page 41: Eclipse Memory Analyzer MAJUG November 2008

41

Die Klasse java.util.concurrent.CopyOnWriteArrayList (ab JDK 1.5) verwendet dieseStrategie

Page 42: Eclipse Memory Analyzer MAJUG November 2008

42

Page 43: Eclipse Memory Analyzer MAJUG November 2008

4343

Page 44: Eclipse Memory Analyzer MAJUG November 2008

44