7. Performance und Speicherauslastung

Werbung
7. Performance und Speicherauslastung
•
•
•
•
•
Java-Parameter mit Performance-Einfluss
Versteckte Speicherlecks
Direkte Zeitmessung in Java
Konzept von Performance-Messwerkzeugen
Netbeans-Profiler
Software-Qualität
Stephan Kleuker
232
Typische Probleme
• Programme zur Zeit- und Speichermessung beeinflussen
Laufzeit und verbrauchten Speicher
• Gerade bei Laufzeitbetrachtungen können durch
langsamere Abläufe neue Effekte entstehen
• Testszenario muss in realistischer Zeit messbar sein
• generell sollten auf Testrechner wenig oder einfach bzgl.
Speicher- und Rechenzeitverbrauch zu kalkulierende
Programme laufen
• oftmals ist mehrmalige Messwiederholung sinnvoll
• bei Nutzung von Zufallswerten muss man Werte entweder
speichern oder Versuche häufig wiederholen
• Java VM kann recht flexibel bzgl. Speicher gestartet werden;
entspricht ggfls. Optimierungsaufgabe für Applikation
• man kann Strategie für Java VM Garbage Collector ändern
Software-Qualität
Stephan Kleuker
233
Parameter von java mit Performance-Einfluss
• Direkte Parameter für die Java VM
-Xbatch Disable background compilation.
-Xdebug Start with the debugger enabled.
-Xnoclassgc Disable class garbage collection.
-Xincgc Enable the incremental garbage collector.
-Xmsn Specify the initial size, in bytes, of the memory
allocation pool. (-Xms6144k -Xms6m)
-Xmxn Specify the maximum size, in bytes, of the memory
allocation pool. (-Xmx81920k -Xmx80m)
-Xssn Set thread stack size.
http://download.oracle.com/javase/6/docs/technotes/tools/w
indows/java.html
Software-Qualität
Stephan Kleuker
234
Parameter von javac mit Performance-Einfluss
• Direkte Parameter für den Java-Compiler
-g Generate all debugging information, including local
variables.
-verbose Verbose output. This includes information about
each class loaded and each source file compiled.
-target version Generate class files that target a specified
version of the VM. (1.1 1.2 1.3 1.4 1.5 (also 5) and 1.6
(also 6))
-Xlint Enable all recommended warnings. (Passt hier nicht
hin, ist aber wichtig für QS ☺)
• http://download.oracle.com/javase/6/docs/technotes/tools
/windows/javac.html
Software-Qualität
Stephan Kleuker
235
Verstecktes Speicherleck (1/3)
package boese;
import
import
import
import
import
java.io.File;
java.io.FileWriter;
java.io.IOException;
java.util.ArrayList;
java.util.List;
public class MachAuf {
public List<FileWriter> fwl = new ArrayList<FileWriter>();
public void steuern() throws IOException {
int anzahl = 0;
while (anzahl != 42) {
System.out.print("Anzahl: ");
anzahl = Eingabe.leseInt();
System.out.print("Datei: ");
oeffnen(Eingabe.leseString(), anzahl);
}
Stephan Kleuker
} Software-Qualität
236
Verstecktes Speicherleck (2/3)
public void oeffnen(String name, int anzahl)
throws IOException {
for (int i = 0; i < anzahl; i++){
FileWriter fw= new FileWriter(
new File(".\\bah\\"+name + i + ".dof"));
fw.write(42);
fwl.add(fw);
}
}
public static void main(String[] arg) throws IOException {
new MachAuf().steuern();
}
}
Software-Qualität
Stephan Kleuker
237
Verstecktes Speicherleck (3/3)
Programmstart
Software-Qualität
Stephan Kleuker
238
Java hat eigenen Profiler
• Option der JavaVM -Xprof (Ausgabe wird auch von
Werkzeugen genutzt)
Software-Qualität
Stephan Kleuker
239
Zeitmessung selbst gestrickt (1/6)
• Szenario: Abteilung mit mehreren Projekten, Projekte mit
mehreren Mitarbeitern
• Frage nach passenden Typ für projekte, mitarbeiter
Software-Qualität
Stephan Kleuker
240
Zeitmessung selbst gestrickt (2/6) - Ausschnitte
public class Abteilung extends Orgeinheit {
// hier verschiedene Set-Implementierungen testbar
// analog auch in Projekt
private Set<Projekt> projekte = new HashSet<Projekt>();
public List<String> mitarbeiterInProjekten(int nr){
List<String> ergebnis = new ArrayList<String>();
for(Projekt p:projekte)
if(p.suchenBeiNr(nr)!=null)
ergebnis.add(p.getName());
return ergebnis;
}
// ...
}
Software-Qualität
Stephan Kleuker
241
Zeitmessung selbst gestrickt (3/6) - Ausschnitte
public class Projekt extends Orgeinheit{
private Set<Mitarbeiter> mitarbeiter
= new HashSet<Mitarbeiter>();
public Mitarbeiter suchenBeiNr(int nr){
for(Mitarbeiter m:mitarbeiter)
if(m.getNr()==nr)
return m;
return null;
}
public class Mitarbeiter extends Orgeinheit { ... }
Software-Qualität
Stephan Kleuker
242
Zeitmessung selbst gestrickt (4/6) - Testszenario
public Lastdaten() {
int anzahl=10000;
long vorher = System.currentTimeMillis();
long summe = 0;
long gestoppt;
List<Mitarbeiter> m = new ArrayList<Mitarbeiter>();
List<Projekt> p = new ArrayList<Projekt>();
List<Abteilung> a = new ArrayList<Abteilung>();
for (int i = 0; i < anzahl; i++)
m.add(new Mitarbeiter(new Date().toString()));
for (int i = 0; i < anzahl/10; i++) {
Projekt pr = new Projekt(new Date().toString());
for (int j = 0; j < anzahl/100; j++)
pr.mitarbeiterHinzu(m.get((int) (m.size()* Math.random())));
p.add(pr);
}
for (int i = 0; i < anzahl/100; i++) {
Abteilung ab = new Abteilung(new Date().toString());
for (int j = 0; j < anzahl/1000; j++)
ab.projektHinzu(p.get((int) (p.size() * Math.random())));
a.add(ab);
} Software-Qualität
Stephan Kleuker
243
Zeitmessung selbst gestrickt (5/6) - Testszenario
gestoppt=System.currentTimeMillis();
summe +=(gestoppt-vorher);
System.out.println("verbraucht erstellen: "+(gestoppt - vorher));
vorher = System.currentTimeMillis();
for(int i=0;i<anzahl;i++)
for(Abteilung ab:a)
ab.mitarbeiterInProjekten(i);
gestoppt=System.currentTimeMillis();
summe +=(gestoppt-vorher);
System.out.println("verbraucht auslesen: "+(gestoppt - vorher));
vorher = System.currentTimeMillis();
for(int i=0;i<anzahl;i++)
for(Abteilung ab:a)
ab.mitarbeiterEntfernen(i);
gestoppt=System.currentTimeMillis();
summe +=(gestoppt-vorher);
System.out.println("verbraucht loeschen: "+(gestoppt - vorher));
System.out.println("gesamt verbraucht: " + summe);
}
Software-Qualität
Stephan Kleuker
244
Zeitmessung selbst gestrickt (6/6) - Ergebnisse
Klasse
HashSet
LinkedHashSet
CopyOnWriteArraySet
erstellen auslesen löschen
170
174
181
180
230
224
37088
36925
26444
24870
15396
15253
23664
23503
14161
13478
14252
14033
gesamt
60922
60602
40786
38528
29878
29510
private Set<Projekt> projekte = new Klasse<Projekt>();
private Set<Mitarbeiter> mitarbeiter
= new Klasse<Mitarbeiter>();
Software-Qualität
Stephan Kleuker
245
Variante (1/2)
• Objekte werden sortierbar:
public class Orgeinheit implements Comparable<Orgeinheit>{
@Override
public int compareTo(Orgeinheit o) {
return nr-o.nr;
} ...
• statt in Projekt:
public void mitarbeiterLoeschen(int nr){
mas.remove(suchenBeiNr(nr));
}
• neu in Projekt:
public void mitarbeiterLoeschen(int nr){
Mitarbeiter m = suchenBeiNr(nr);
if(m!=null)
mitarbeiter.remove(m);
} Software-Qualität
Stephan Kleuker
246
Variante (2/2)
Klasse
HashSet
LinkedHashSet
CopyOnWriteArraySet
ConcurrentSkipListSet
TreeSet
Software-Qualität
erstellen auslesen löschen
159
143
151
150
210
209
187
177
168
162
37202
36965
25944
25600
15482
15589
30882
32112
39322
37908
Stephan Kleuker
23375
23187
13981
13662
8263
8253
15999
17194
20320
19453
gesamt
60736
60295
40076
39412
23955
24051
47068
49483
59720
57523
247
Konzept von Performance-Messwerkzeugen
• ähnlich zum letzten Beispiel wird Java-Code erweitert
• java -agentlib:hprof (hprof als Beispiel)
• Erweiterungen melden Informationen an Messerwerkzeug,
welches protokolliert
• Meldungen sollen erlauben, das Verhalten des Messwerkzeugs
heraus zu rechnen, genauer:
– Java hat Java Virtual Machine Tool Interface (JVMTI)
– ermöglicht als Aufrufargument einen Java Agent
– Java Agent ist spezielle Klasse
• aufgerufen bevor irgendwas passiert (vor main)
• Java Agent kann Filter installieren; bekommt mit, wenn
Klassen geladen werden und kann diese verändern
• http://java.sun.com/developer/technicalArticles/J2SE/jvm_ti/
• (Ansatz vergleichbar mit Aspect-opriented Programming)
Software-Qualität
Stephan Kleuker
248
Beispiel: Netbeans Profiler (1/7)
Software-Qualität
Stephan Kleuker
249
Beispiel: Netbeans Profiler (2/7)
Software-Qualität
Stephan Kleuker
250
Beispiel: Netbeans Profiler (3/7)
Software-Qualität
Stephan Kleuker
251
Beispiel: Netbeans Profiler (4/7)
Klasse
Hinzu InProjekten Entfernen gesamt
HashSet
133
46486
40577 88379
LinkedHashSet
128
38473
34285 74088
CopyOnWriteArraySet
3468
23752
24671 53088
ConcurrentSkipListSet
1617
48149
40914 91983
TreeSet
888
48805
39259 90200
• Vorletzten beiden Klassen sind thread-safe; dies kann
Unterschied zu erster Messung erklären
• TreeSet, ConcurrentSkipListSet benötigten Comparable<T>
• Wieder: HashSet wie TreeSet; LinkedHashSet besser
• Test war mit kleinen Objekten (Einfluss?)
Software-Qualität
Stephan Kleuker
252
Beispiel: Netbeans Profiler (5/7)
Software-Qualität
Stephan Kleuker
253
Beispiel: Netbeans Profiler (6/7)
Software-Qualität
Stephan Kleuker
254
Beispiel: Netbeans Profiler (7/7)
Klasse
Top 3 Speicherverbrauch
HashSet
LinkedHashSet
CopyOnWriteArraySet
ConcurrentSkipListSet
TreeSet
Software-Qualität
Stephan Kleuker
255
Zusammenfassung
• Definition des Testszenarios ist hier sehr komplexe Aufgabe
• Testergebnisse können von vielen kleinen Parametern
(Objektgrößen, Systemeinstellungen) abhängen
• Kleine Änderungen können große Effekte haben
• Performance- und Speicherverbrauchsmessung oft nicht
ganz exakt durchführbar
• Zentrale Frage: welche Methode wird wie of aufgerufen und
verbraucht wieviel Zeit
• Zentrale Frage: Welche Onjekte verbrauchen wieviel
Speicherplatz
• Werkzeugunterstützung ist vorhanden
Software-Qualität
Stephan Kleuker
256
Herunterladen