# Performancekiller?



## tomkruse (14. Feb 2004)

Hi!

Da ich viel mit Handys mache und die ja eine sehr eingeschränke Prozessorleistung haben würde mich mal interessieren, was so die echten Performancekiller sind. Also was sollte man auf jeden Fall vermeiden, wenn man nicht verschwenderisch sein will?

Welche Tricks gibt es so, bzw. was muß man beachten?

Cu - Tom.


----------



## bygones (14. Feb 2004)

keine String aneinanderhängen mit dem String Object, sonder mit StringBuffer:

Statt:
	
	
	
	





```
String s = "";
for(int i = 0; i< 1000; i++) {
   s = " " + i;
}
```

Eher:
	
	
	
	





```
StringBuffer buffer = new StringBuffer(1000);
for(int i = 0; i< 1000; i++) {
  buffer.append(i);
}
```

Versuchen auf synchronized Methoden zu verzichten, versuchen Methoden mit wenig Paramter aufzurufen.

Eher LinkedList / ArrayList anstatt Vector

Sowohl bei Datei schreiben als auch beim lesen einen Buffe verwenden.

Ansonsten noch:


> Jede Allozierung von Speicher kostet Rechenzeit. Der Speicher muß entweder vom Betriebssystem oder vom Laufzeitsystem der VM beschafft werden. Auch das (automatische) Initialisieren des Speichers kostet Zeit. Das Anlegen eines Arrays mit 1000 Elementen dauert wesentlich länger als das eines mit 10 Elementen.
> 
> Objekte mit aufwendigen Konstruktoren benötigen möglicherweise viel Zeit zur Initialisierung. Bei ihnen kann es sinnvoll sein, sie zu »recyceln«. Dazu werden sie nach Gebrauch in einer geeigneten Datenstruktur gesammelt und können dem nächsten Interessenten (alternativ zur Erzeugung eines neuen Objekts) zur Verfügung gestellt werden. Vor der Verwendung muß dieser das Objekt natürlich geeignet initialisieren.
> 
> ...


----------



## tomkruse (14. Feb 2004)

Hi!

Danke! Das hilft mir schon mal sehr weiter. 
Irgendwo hab ich gelesen, daß der Typ long sehr langsam sein soll und der Typ int wesentlich schneller im Zugriff ist.
Arrays sind angeblich auch sehr langsam, weil bei jedem Zugriff ein null-check durchgeführt wird.


```
x=a[5];
x=x+3;
x=x*2;
x++;
a[5]=x;
```

ist angeblich schneller als


```
a[5]=a[5]+3;
a[5]=a[5]*2;
a[5]++;
```

Ok, ist sicher nicht so dramatisch, weil nicht sooo viele Zugriffe auf das Array stattfinden, aber in einer
Schleife könnte sich das schon eher auswirken, oder?

Cu - Tom.


----------



## jptc.org (18. Feb 2004)

tomkruse hat gesagt.:
			
		

> Hi!
> Irgendwo hab ich gelesen, daß der Typ long sehr langsam sein soll und der Typ int wesentlich schneller im Zugriff ist.
> Arrays sind angeblich auch sehr langsam, weil bei jedem Zugriff ein null-check durchgeführt wird.
> 
> ...



Also im Allgemeinen sollte man in Schleifen vermeiden irgendwelche Methoden für den Zugriff auf Variablen aufzurufen (da fallen auch Arrays drunter). Es ist schneller vor dem Aufruf der Schleife diese Werte auszulesen und in temporäre Variablen zu speichern. Müssen in der Schleife immer neue Werte ausgelesen werden, so empfiehlt isch die Variablen dafür vor den Schleife zu definieren und in der Schleife immer wieder zu überschreiben.

Int ist schneller als long, da ja die Verarbeitung von int optimiert ist (nicht java sondern der prozessor kann damit besser umgehen). naja will man zeit sparen kann man auch gerne auf short, byte und (char) verzichten, da diese Typen intern immer wie int behandelt werden.

Karsten Voigt
http://www.java-performance-portal.org


----------



## tomkruse (14. Mrz 2004)

Hi!

Und schon wieder habe ich etwas gelesen was mich etwas verwundert hat: Der Zugriff auf public Membervariablen scheint deutlich schneller zu sein als wenn man das Ganze über Zugriffsmethoden realisiert. Auch wenn die Zugriffs methoden mehr dem Grundsatz vom Objektorientiertem Design entsprechen, so kosten sie doch einiges. Methodenaufrufe scheinen überhaupt ziemlich was "extra zu kosten". Also es ist zwar übersichtlich, alles in handliche Methoden zu zerlegen, aber es dürfte einiges bringen, Methoden, die nur an wenigen Stellen aufgerunfen werden lieber zu "inlinen".

Cu - Tom.


----------



## Tobias (14. Mrz 2004)

@deathbyaclown: Woher ist das Zitat??

mpG
Tobias


----------



## schalentier (15. Mrz 2004)

@tomkruse
wo hast du das her, wuerd mich mal interessieren. klar ist ein methodenaufruf langsamer als auf ne membervar selbst, da einfach mehr code auszufuehren ist. allerdings glaub ich kaum, dass sich das _signifikant_ auf die performance auswirkt. da bringt glaub ich das schluesselwort "final" mehr, wodurch die spaete bindung verhindert wird. 
gibt es inline als keyword bei java?
sollte das nicht eigentlich ein guter jit-compiler selbst erkennen und machen?

achso: 
arrayzugriffe sind langsamer, da bei jedem zugriff (lesend und schreibend) ein ArrayBoundCheck durchgefuehrt wird, so dass im zweifelsfall eine OutOfBoundsException geworfen wird, anstatt irgendwelchen speicher zu ueberschreiben.
Is ein richtiges Array eigentlich spuerbar schneller als eine ArrayList oder was vergleichbares?

gl&hf


----------



## bygones (15. Mrz 2004)

@tobias:

Zitat stammt aus dem Javabuch http://www.javabuch.de

Achja da steht auch noch:



> Seit der Version 1.2 des JDK stehen mit den Klassen LinkedList und ArrayList auch alternative Listenimplementierungen zur Verfügung, die anstelle von Vector verwendet werden können. Hier ist jedoch Vorsicht geboten, soll das Programm nicht langsamer laufen als vorher. Die Klasse LinkedList implementiert die Datenstruktur in klassischer Form als doppelt verkettete Liste ihrer Elemente. Zwar entfallen dadurch die Kopiervorgänge, die beim Erweitern des Arrays erforderlich waren. Durch die Vielzahl der allozierten Objekte, in denen die Listenelemente und die Zeiger gespeichert werden müssen, und die teilweise ineffiziente Implementierung einiger Grundoperationen (insbesondere add) hat sich LinkedList jedoch im Test als relativ ineffizient herausgestellt. Wesentlich bessere Ergebnisse gab es mit der Klasse ArrayList. Sie ist ähnlich wie Vector implementiert, verzichtet aber (wie die meisten 1.2er Collections) auf die synchronized-Attribute und ist daher - insbesondere bei aktiviertem JIT und Zugriff mit add und get sehr - performant.
> .....
> Seit der Version 1.2 des JDK stehen mit den Klassen LinkedList und ArrayList auch alternative Listenimplementierungen zur Verfügung, die anstelle von Vector verwendet werden können. Hier ist jedoch Vorsicht geboten, soll das Programm nicht langsamer laufen als vorher. Die Klasse LinkedList implementiert die Datenstruktur in klassischer Form als doppelt verkettete Liste ihrer Elemente. Zwar entfallen dadurch die Kopiervorgänge, die beim Erweitern des Arrays erforderlich waren. Durch die Vielzahl der allozierten Objekte, in denen die Listenelemente und die Zeiger gespeichert werden müssen, und die teilweise ineffiziente Implementierung einiger Grundoperationen (insbesondere add) hat sich LinkedList jedoch im Test als relativ ineffizient herausgestellt. Wesentlich bessere Ergebnisse gab es mit der Klasse ArrayList. Sie ist ähnlich wie Vector implementiert, verzichtet aber (wie die meisten 1.2er Collections) auf die synchronized-Attribute und ist daher - insbesondere bei aktiviertem JIT und Zugriff mit add und get sehr - performant.


----------



## tomkruse (20. Mrz 2004)

schalentier hat gesagt.:
			
		

> @tomkruse
> sollte das nicht eigentlich ein guter jit-compiler selbst erkennen und machen?



Hi!

Ich programmiere hauptsächlich auf mobilen Devices und da ist schon von vorneherein nicht so eine enorme Rechenleistung zu erwarten. Dementsprechend wirkt sich zusätzlicher Code schon ziemlich aus. Einen guten jit-Compiler kann man auf Handys leider ebensowenig voraussetzen wie einen guten GarbageCollector. 

Wie ist das nun nochmal genau mit final? Was erreicht man damit (in punkto performance) und warum eigentlich?

Cu - Tom.


----------



## schalentier (21. Mrz 2004)

Sagt dir das schluesselwort "virtual" von c++ was? final ist genau das gegenteil.

hier zwei einfache klassen:

```
class Foo {
  public void doIt(){ sout("Hi von Foo"); }
}
class Bar extends Foo {
  public void doIt() { sout("Hi von Bar"); }
}
...
Foo foo = new Foo();
foo.doIt(); // "Hi von Foo"
foo = new Bar();
foo.doIt(); // "Hi von Bar"
```

Das heisst, wenn ein Aufruf an foo.doIt() geht, muss die vm erstmal testen, welche doIt-Methode ausgefuehrt werden soll. (doIt() in Foo oder eine doIt() von einer Klasse, die von Foo abgeleitet ist)
Das nennt man spaete bindung und es benoetigt eine gewisse zeit nur fuer den test, welche methode genutzt werden soll.

mit dem schluesselwort final unterbindet man genau das. man kann also eine methode nicht mehr ueberschreiben, was einen geschwindigkeitsvorteil bringt.


----------



## tomkruse (21. Mrz 2004)

Hi!

Ok, so ähnlich habe ich mir das eh gedacht. danke.
Nur, wenn ich jetzt die Methode doIt() der Classe bar final mache, dann ändert das nichts daran, daß immer noch nachgesehen werden muß, welches doIt() jetzt ausgeführt werden muß, das von  Bar oder das von Foo, oder sehe ich das jetzt falsch?

Cu - Tom.


----------



## schalentier (21. Mrz 2004)

```
class Foo { 
  public final void doIt(){ sout("Hi von Foo"); } 
} 
class Bar extends Foo { 
  public void doIt() { sout("Hi von Bar"); } 
  //--- COMPILER FEHLER ////
}
```

eine final methode kann man nicht ueberschreiben, da kommt ein compilerfehler


----------



## tomkruse (27. Mrz 2004)

Hi!

Ich meinte, wenn man die Methode, die die andere überschreibt final macht. Das kann man ja.

Cu - Tom.


----------

