Java Performance Tuning

Werbung
Java Performance Tuning
Performance Tuning is similar to playing a strategy game but happily you usually get paid
for it.
Schlechte Performanz kaschieren






Bernhard Mähr
Eigentlich kein Tuning
Benutzer findet das Programm schnell
Responsabiltiy
Trennung von UI und Arbeits-Thread
Animationen um Wartezeiten zu „verkürzen“ siehe
zB Fading-Effekte in WindowsXP
Vorarbeiten zB während Texteingaben durchführen
gibt dem Benutzer das Gefühl einer blitzschnellen
Anwendung
Java Performance Tuning
2/25
Allgemeines






Bernhard Mähr
Sollte erst an der fertigen Anwendung durchgeführt
werden
Performance Tuning widerspricht meist
objektorientiertem Design
Code wird unübersichtlicher
Aber: Beim Application-Design Performance nicht
ignorieren
Änderungen können auf anderen Platformen
Performanz-Nachteile bringen
Neusten Compiler verwenden
Java Performance Tuning
3/25
Schritte
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Bernhard Mähr
Benchmark einbauen und Tests ausführen
Bottlenecks identifizieren
Eines aus den Top 5 Bottelnecks wählen (abhängig
von bremsender Wirkung und Behebbarkeit)
Ausgewählte(s) Methode/Datenstruktur/Objekt/…
analysieren
Eine Änderung durchführen
Perfomance-Messung durchführen
Falls die Änderung nicht den gewollten Effekt
erzielte vielleicht einen Schritt zurück
Solange noch Verbesserungen möglich sind weiter
bei Schritt 4
Messung der Gesamtverbesserung
Wieder mit Schritt 1 beginnen da sich meist das
gesamte Perfomance-Profil geändert hat
Java Performance Tuning
4/25
Bottelneck auswählen




Bernhard Mähr
Programmteil der viel Rechenzeit verwendet
Methode mit 1% Rechenzeit -> max. 1% schneller
wenn Algorithmus um 100% schneller
Methode mit 10% Rechenzeit um 50% schneller ->
Gesamtperformance um 5% besser
Nur das Tunen was wirklich bremst
Java Performance Tuning
5/25
Compiler Optimierungen

arr[1]=arr[1]+5; -> arr[1]+=5;
y=x/2; -> y=x>>1;
z=x*4; -> z=x<<2;
T y = new T(5); T x = (T)y;
int x = 0;
int x = 1; x = 2;
int duration = 24*60*60;
String s = „“ + 24 + „hours “ + „online“;

Dummy case-Zweige für Switch-Anweisungen







Bernhard Mähr
Java Performance Tuning
6/25
Inlineing


Bernhard Mähr
final, private und static
Methoden können eingefügt
werden. Geschieht meist nur
private int m1() { return 5; }
keine lokalen Variablen
private int m2() { return m1(); wenn
}
verwendet werden
public interface A {
public static final boolean DEBUG = false;
}
public class B {
public static int foo() {
if (A.DEBUG) System.out.println(„Check“);
return 0;
Der Compiler aus dem SDK führt
}
Inlining nur bei Konstanten aus
}
Interfaces aus. Die If-Anweisung
wird zur Compilezeit komplett
entfernt.
Java Performance Tuning
7/25
Optimierungen in Standardanweisungen







Bernhard Mähr
Datentyp int ist schneller als long, byte, short,…
Zugriff auf lokale Variablen ist schneller als Zugriff
auf static Variablen
Zugriff auf einfache Variablen ist schneller als Zugriff
auf Arrays oder Objekte
Kurzschluß-Auswertung beachten
//statt
if (n == Integer.MIN_VALUE || n>0){
//lieber
if (n>0 || n == Integer.MIN_VALUE){
Native-Methoden verwenden wenn möglich (zB
arraycopy() statt Schleife)
Zugriff auf eindimensionale Arrays ist schneller wie
auf mehrdimensionale
Java Performance Tuning
8/25
Canonicalization



Bernhard Mähr
public interface GENDER {
public static final int FEMALE=1;
public static final int MALE=2;
}
if (user.gender==FEMALE) {…} //Inlining durch Complier
public class STATUS {
public static final String ONLINE=„Online“;
public static final String OFFLINE=„Offline“;
}
if (user.state==STATUS.ONLINE) {…}
Boolean t1 = new Boolean(true); Boolean.TRUE;
System.out.println(t1==Boolean.TRUE);
//false
System.out.println(t1.equals(Boolean.TRUE)); //true
Java Performance Tuning
9/25
Objekte







Bernhard Mähr
Erzeugung und GC ist aufwendig
Möglichst wenige Objekte verwenden
TypeCasts sind teuer
instanceof abfragen statt Exception von TypeCast
abfangen
Einfache Datentypen statt Objekten
Objekte wiederverwenden -> Objektpool
Objekte im voraus erzeugen
Java Performance Tuning
10/25
Initialisieren vs Clonen






Bernhard Mähr
static int[] Ref_a1 = {1,2,3,4,5,6,7,8,9};
static int[][] Ref_a2 = {{1,2},{3,4},{5,6},{7,8}};
int[] a1 = {1,2,3,4,5,6,7,8,9};
//schneller als int[] array1 = (int [])Ref_a1.clone();
int[][] a2 = (int [][])Ref_a2.clone();
//schneller als int[][] a2 = {{1,2},{3,4},{5,6},{7,8}};
Komplizierte Objekte können schneller geklont als
initialisiert werden
Mittels Factory-Pattern sehr gut implementierbar
private static Something MASTER = new Something();
public static Something getNewSomething() {
return (Something) MASTER.clone();
}
Java Performance Tuning
11/25
Wiederverwenden von Parameter-Objekten






Bernhard Mähr
public Dimension setSize(Dimension d) {
…
d.width=5; d.height=10;
return d;
}
Probleme?
realSize = O.setSize(wantedSize);
wantedSize.height=7; //realSize.height = ?
Lösungen:
class FixedDimension {
final int height;
final int width;
}
Alle Methoden müssen für die Verwendung von
FixedDimension geändert werden
Java Performance Tuning
12/25
Wiederverwenden von Parameter-Objekten




Bernhard Mähr
private static final Dimension D = new Dimension(0,0);
public Dimension setSize(Dimension d) {
Dimension newd = (Dimension)D.clone();
setSize(d, newd);
return newd;
}
public void setSize(Dimension d, Dimension retd) {
…
retd.width = 5;
retd.height = 10;
}
Verwendung wie bisher, für Performance-Tuning
kann die 2te Methode verwendet werden
o.setSize(d,d);
Java Performance Tuning
13/25
Schleifen






for(long i=0; i<collection.size(); i++) {
countArr[0]=countArr[0] + 5 * points;
}
Unnötige Anweisungen aus der Schleife entfernen
Methoden-Aufrufe minimieren
Array-Zugriffe vermeiden
Umgekehrte FOR-Schleife
int
intcount=countArr[0];
addpoints = points * 5;
count=countArr[0];
int
intaddpoints=5*points;
addpoints
iter
addpoints=5*points;
= collection.size()*50000;
= points;
points * 5;
for(int
i=collection.size();
--i>=0; ){
int i=collection.size()*50000;
addpoints
iter
count
count=countArr[0];
==collection.size()*50000;
countArr[0];
= points;
count+=addpoints;
for(long
for(int
for(;
--i>=0;
i=0;
i=collection.size()*50000;
i=iter;
i=0;i<iter;
i<collection.size()*50000;
i<iter;
){--i>=0;)
i++)
i++)
{{{
--i>=0;
i++)
){ {
} count+=addpoints;
countArr[0]=countArr[0]
count=count
count+=
count=count
countArr[0]=countArr[0]
addpoints;
++addpoints;
addpoints;
++5
addpoints;
5**addpoints;
points;
countArr[0]=count;
}
countArr[0] = count;
countArr[0]=count;
Laufzeit
Laufzeit
Laufzeit
Laufzeit
Bernhard Mähr
1.3.1
1.3.1
1.4.1
1.4.1
Code
Code
Code
Code
/
/
/
/
1.1.8 No JIT:
1.1.8:
1.4.1 Client:
1.4.1 Server:
Java Performance Tuning
39,997
228,559
128,505
98,862
44,384
41,610
225,844s s/ /194%
146,100
44,474
40,769
480%
216%
202%
198%
1111%
624%
1097%
710%
3,305
3,705
1,533
1,513
1,512
2,864 s / 7%
3,505
1,602
16%
18%
14%
17%
8%
36,813
14,591
11,897
6,900
7,651
7,691
31,845s s/ /37%
14,331
6,980
6,229
34%
30%
155%
71%
58%
70%
25,046
4,136
4,116
0,701
0,711
20,580s
s/s/20%
/3%
20%
122%
100%
14/25
Schleifen / Exceptions





Bernhard Mähr
Exception Terminated Loops
try {
for(int i=0;;i++) {…}
} catch (Exception e) {}
Bei vielen Schleifendurchläufen schneller aber nicht
sauber
Try-Blocks ohne geworfene Exception bremsen aber
nicht viel (bis JDK 1.1.8)
Try-Blocks mit geworfener Exception sind deutlich
langsamer und sollten im normalen Programmablauf
nicht vorkommen
Java Performance Tuning
15/25
Rekursionen




Bernhard Mähr
public static long fact_rec (int n) {
return n*fact_rec(n-1);
}
public static long fact_iter (int n) {
long result = 1;
while (n>1) {
result *= n--;
}
return result;
}
Iterative Version braucht nur 88% der Zeit
Gecachte Zwischenergebnisse: 4%
Java Performance Tuning
16/25
Laden beschleunigen




Bernhard Mähr
Spash-Screen
Unkompremierte JAR-Archive
Preload von Klassen (Achtung: Caching der VM nicht
behindern)
Lazy-Initialisation
Java Performance Tuning
17/25
String / StringBuffer



Bernhard Mähr
Insert, Append, Delete ist auf StringBuffer viel
schneller als auf Strings
Substring auf String kopiert nichts -> schnell
toString() auf StringBuffer kopiert nichts -> schnell
allerdings wird Größe nicht verkleinert
Java Performance Tuning
18/25
Threads/Synchronized




Bernhard Mähr
Falsch eingesetzte Threads und jedes Synchronized
bremst
Ein Thread, der die Aufgaben an einen anderen
übergibt, und dann auf deren Beendigung wartet ist
sinnlos und langsam!
Syncronized Methoden sind 10 mal (mit JIT
Compilern) bis 100 mal langsamer
Synchronisierte Objekte verwenden und bei
Performance-Problemen auf die Unsynchronisierten
ausweichen.
Java Performance Tuning
19/25
Syncronized Wrappers für eigene Klassen

Bernhard Mähr
public interface Adder {
public void add(int aNumber);
}
public class UnsyncedAdder implements Adder {
int total;
int numAdditions;
public void add(int add){ total+=add; numAdditions++;}
}
public class SyncedAdder implements Adder {
Adder a;
public SyncedAdder(Adder a) { this.a = a; }
public synchronized void add( int add) { a.add(add); }
}
Java Performance Tuning
20/25
Collections
Interface Class
Sync
Eigenschaften
Map
HashMap
Nein
Schnellstes Map
HashTable
Ja
Langsamer als HashMap aber schneller
als sync. HashMap
TreeMap
Nein
Langsamer als HashTable; Geordnete
Iteration der Keys möglich
HashSet
Nein
Schnellstes Set; Langsamer als
HashMap aber Set
TreeSet
Nein
Langsamer als HashSet; Geordnete
Iteration der Keys möglich
ArrayList
Nein
Schnellste Liste
Vector
Ja
Langsamer als ArrayList aber schneller
als sync ArrayList
Stack
Ja
Gleich schnell wie Vector; LIFO Queue
LinkedList
No
Langsamer als andere List-Klassen; für
Spezial-Fälle schneller
Set
List
Bernhard Mähr
Java Performance Tuning
21/25
Selber implementieren?



Bernhard Mähr
Sind die Implementierungen der Java-Libaries
optimal?
An den Verwendungszweck angepaßte
Implementierung senkt die Ausführungszeit auf bis
zu 0.7%
Selbstgeschriebene IntArrayList statt der ArrayList
verwenden
Java Performance Tuning
22/25
Text einlesen (Lange Zeilen)
1.2
1.2 kein
JIT
1.3
HotSpot
1.0
HotSpot
2nd Run
1.1.6
Unbuffered
Inputstream
1951%
3567%
1684%
1610%
1641%
1341%
Buffered
Inputstream
100%
450%
52%
56%
45%
174%
8K Buffered
Inputstream
102%
477%
50%
45%
48%
225%
Buffered
Reader
47%
409%
43%
74%
41%
43%
Custom-built
Reader
26%
351%
37%
81%
36%
15%
Custom
reader and
converter
12%
69%
18%
77%
17%
10%
Bernhard Mähr
Java Performance Tuning
23/25
Text einlesen (Kurze Zeilen)
1.2
1.2 kein
JIT
1.3
HotSpot
1.0
HotSpot
2nd Run
1.1.6
Unbuffered
Inputstream
1308%
2003%
1101%
1326%
1232%
871%
Buffered
Inputstream
100%
363%
33%
50%
54%
160%
8K Buffered
Inputstream
101%
367%
31%
41%
54%
231%
Buffered
Reader
111%
554%
39%
149%
45%
127%
19%
237%
28%
94%
26%
14%
9%
56%
21%
80%
53%
8%
Custom-built
Reader
Custom
reader and
converter
Bernhard Mähr
Java Performance Tuning
24/25
Quellen



Bernhard Mähr
Jack Shirazi: Java Performance Tuning
ab Feb 2003 neue stark erweiterte Auflage
http://www.javaperformancetuning.com/
http://www2.cs.cmu.edu/~jch/java/optimization.html
Java Performance Tuning
25/25
Herunterladen