Effiziente Java Programmierung Seminar Implementierung moderner virtueller Maschinen am Beispiel von Java SS 2009 von Reinhard Klaus Losse 20. Mai 2009
Gliederung Definition Effizienz Werkzeuge zum Messen von Effizienz Beispiel aus der Praxis Mögliche Bösewichte Tests 2
1. Definition Effizienz Ein Programm ist effizient, wenn: seine Rechengeschwindigkeit niedrig ist, sein Speicherverbrauch niedrig ist und die Geschwindigkeit von Ein-/ Ausgabeoperationen niedrig ist. hier: Effizienz auf der Ebene der JVM und des Bytecodes 3
2. Messwerkzeuge Windows-Task-Manager äquivalente Tools in Unix/ Linux: top, ps, netstat, vmstat, iostat, sar (System Accounting Reports), truss, strace Profiler, z. B. Hprof Methoden java.lang.system.currenttimemillis() und java.lang.system.nanotime() (seit Java 5) 4
Profiler: Motivation geben z. B. Auskunft darüber: wie viele Objekte vom Typ X existieren, wie viel Speicher sie verbrauchen, wie Zeit ein Programm in Methode y verbringt und wie häufig diese Methode aufgerufen wurde 5
Geschichte von Hprof war in den Java-Versionen 1.2 bis 5 als Teil des experimentellen Java Virtual Machine Profiler Interface (JVMPI) enthalten wurde in Java 5 auf dem neuen Java Virtual Machine Tool Interface (JVM TI) implementiert, das das JVMPI ersetzte 6
Aufruf von Hprof bis Java 5: java -Xrunhprof[:options] ToBeProfiledClass ab Java 5: java -agentlib:hprof[=options] ToBeProfiledClass Liste aller Optionen: java -agentlib:hprof=help 7
Aufruf von Hprof Hprof speichert die Ergebnisse des Profilings in eine Datei jede Datei enthält: Liste aller Threads Liste von nummerierten Stacktraces 8
Aufruf von Hprof jede Datei kann darüber hinaus enthalten: Heap-Dump Liste aller Objekttypen geordnet nach dem Speicherverbrauch (Sites) Liste aller Methoden geordnet nach zeitlichen Stichproben (CPU Samples) Liste aller Methoden geordnet nach dem Zeitverbrauch (CPU Time) 9
Beispiel aus der Praxis String-Variante String hallowelt = Hallo Welt ; String weite = weite ; String hallo = hallowelt.substring(0, 7); String welt = hallowelt.substring(7); String halloweitewelt = hallo.concat(weite).concat(welt); 4 Objekte 10
3. Beispiel aus der Praxis StringBuffer-Variante String hallowelt = Hallo Welt ; String weite = weite ; StringBuffer stringbuffer = new StringBuffer(halloWelt); stringbuffer.insert(7, weite); String halloweitewelt = stringbuffer.tostring(); 3 Objekte 11
Beispiel aus der Praxis String-Variante mit + String hallowelt = Hallo Welt ; String weite = weite ; String hallo = hallowelt.substring(0, 7); String welt = hallowelt.substring(7); String halloweitewelt = hallo + weite + welt; 4 Objekte 12
Beispiel aus der Praxis Messergebnisse: String: 6628217 ns 100% StringBuffer: 7568280 ns 114% String mit +: 9880585 ns 149% Einfügen von Strings erfolgt in Bezug auf den Zeitbedarf am besten mit der Klasse String 13
4. Mögliche Bösewichte Objekt mit vielen Instanzenvariablen Arrays mit vielen Elementen viele Methodenaufrufe häufige Arrayzugriffe häufige Feldzugriffe 14
Schleifen for (int i = 0; i < list.size(); i++) { Object o = list.get(i);... } for (int i = 0, n=list.size(); i < n; i++) { } Object o = list.get(i);... 15
Arrays private int arrayaccessinloop() { } int[] array = new int[1]; for (int i=0; i < 20000000; i++) array[0] += i; return array[0]; 16
5. Tests Testsystem: Windows XP 1 GB Arbeitsspeicher Pentium M 1,86 Ghz Java 6 Durchführung der Tests 1.000-fache Messung der Zeit über nanotime() 17
Objekt- und Arrayerzeugung Erzeugung eines Objekts mit nur einer int- Instanzenvariable Erzeugung eines Objekts mit 18 Instanzenvariablen, 9 int-variablen und 9 String-Variablen Erzeugung eines Arrays mit 0 Elementen Erzeugung eines Arrays mit 5 Elementen 18
Objekt- und Arrayerzeugung Messergebnisse: Objekt mit wenigen Elementen: 1955 ns 100% Objekt mit vielen Elementen: 2793 ns 143% Array mit 0 Elementen: 1676 ns 100% Array mit 5 Elementen: 1955 ns 117% 19
Methodenaufrufe 100.000-facher Aufrufe folgender Methode: <Modifier> int mymethod(int j) { } return j+1; Modifier: public public static private private static 20
Methodenaufrufe Interface: Klasse implementiert ein Interface Interface enthält die Methode mymethod Oberklasse: Klasse erbt von Oberklasse 1. Variante: Klasse überschreibt mymethod 2. Variante: Klasse implementiert die abstrakte Methode mymethod 100.000-facher Aufruf der Methode mymethod 21
Methodenaufrufe letzte Variante: inline for (int i = 0; i < 100000; i++) j = j + 1; direkte Ausführung der Operation statt Methodenaufruf 22
Methodenaufrufe Messergebnisse mit inline: public: 15029284 ns 279% public static: 13376281 ns 249% private: 19297983 ns 359% private static: 13376281 ns 249% abstrakt: 19432637 ns 361% überschreiben: 15029284 ns 279% Interface: 18030224 ns 335% inline: 5377499 ns 100% 23
Methodenaufrufe Messergebnisse ohne inline: public: 15029284 ns 112% public static: 13376281 ns 100% private: 19297983 ns 144% private static: 13376281 ns 100% abstrakt: 19432637 ns 145% überschreiben: 15029284 ns 112% Interface: 18030224 ns 135% 24
Array- und Feldzugriff Zugriff auf das Arrayelement Nr. 10: int[] array = new int[100]; int j = 0; array[10] = 1; for (int i = 0; i < 100000; i++) j = j + array[10]; 25
Array- und Feldzugriff 100.000-facher Zugriff auf ein Feld einer anderen Klasse: public public static 100.000-facher Zugriff auf eine lokale Variable 26
Array- und Feldzugriff Messergebnisse: Arrayzugriff: 6403607 ns 100% Feldzugriff (public): 6857296 ns 107% Feldzugriff (public static): 6469537 ns 101% Feldzugriff (lokal): 6858413 ns 107% 27
Fazit Erzeugung größerer Objekte und Arrays dauert länger als die kleinerer inline bei Methodenaufrufen mit Abstand am schnellsten, gefolgt von statischen Methodenaufrufen private und abstrakt bei Methodenaufrufen am langsamsten, gefolgt von Interface Arrayzugriffe und statische Feldzugriff schneller als sonstige Feldzugriffe aber: JIT-Compiler bringt alles durcheinander 28
Quellen Performant Java programmieren, Hendrik Schreiber, Addison Wesley 2002 HPROF: A Heap/CPU Profiling Tool in J2SE 5.0, http://java.sun.com/developer/technicalarticles/programming/hprof.html, abgerufen am 22.04.2009 JDK 6 Documentation 29