# Performance Tips



## Civilazi (16. Jan 2013)

Hallo ihr,

Performance ist mir teilweise extrem wichtig. 

Kennt jemand ein Buch / Webseite mit Tips zu performantem Programmieren? Beispielsweise habe ich mir sagen lassen, dass der Punkt-Operator teuer ist und wenn ich mehrmals an eine Objektvariable ranwill, ich die dann zwischenspeichern sollte (stimmt das?). 
Also kein Optimieren auf der Algorithmenebene, sondern schon tiefer. 
Ich möchte mir kein Profiling sparen, sondern habe gedacht, dass es evtl. schon während des Implementierens eben performante und nicht so performante Wege gibt, Dinge zu erledigen. Ich verfolge natürlich trotzdem das Ziel, gut lesbaren Code zu schreiben. 

Gibt es solche Tips oder war das nur früher mal aktuell und man sollte die VM einfach machen lassen oder wie sieht es hier aus?  

Vielen Dank für eure Mithilfe.


----------



## nillehammer (16. Jan 2013)

Du beziehst Dich in Deiner Frage ja explizit auf Code. Da empfehle ich das Buch "Effective Java 2nd Edition" von Joshua Bloch. Da wird sehr genau auf guten Code eingegangen, der die von Dir angesprochenen Fehler vermeidet. Darüber hinaus dann noch "Clean-Code" von Robert C. Martin. Das ist zwar nicht nur auf Java gemünzt und nähert sich umfassender dem Thema, aber "Clean-Code" hat meistens auch eine bessere Performance. Beide Bücher sind meiner Meinung nach Pflichtlektüre!

Im Prinzip kann man bei Performance auf Code-Ebene sagen: "Vermeide alles, was unnötig ist." Da Du als Programmierer weißt, wie der Ablauf Deines Programmes sein soll, siehst Du auch selbst, wo das der Fall sein könnte. Ansätze:
- Unnötige Objekterzeugung
- Ungünstig verschachtelte/ mehrfach dürchgeführte Überprüfung von Bedingungen
- String-Konkatenierung mittels des '+'-Operators
- "Schlechte" Objekterzeugung (z.B. new Integer(1), obwohl es die statische Factorymethode valueOf gibt)
- "Schlechte" Algorithmen

Ansonsten kommt es auf die eingesetzte Technologie an. Es gibt halt effiziente Arten, z.B. Abfragen an eine DB zu senden und auch sehr ineffiziente. Wenn Du den Bereich noch eingrenzen könntest, gibts vielleicht noch mehr Empfehlungen.


----------



## Timothy Truckle (16. Jan 2013)

Civilazi hat gesagt.:


> Performance ist mir teilweise extrem wichtig.


Sehr löblich



Civilazi hat gesagt.:


> Kennt jemand ein Buch / Webseite mit Tips zu performantem Programmieren?


Effective Java: A Programming Language Guide (Java Series): Amazon.de: Joshua Bloch: Englische Bücher ist wohl immernoch eine gute wahl.


Civilazi hat gesagt.:


> Beispielsweise habe ich mir sagen lassen, dass der Punkt-Operator teuer ist und wenn ich mehrmals an eine Objektvariable ranwill, ich die dann zwischenspeichern sollte (stimmt das?).


Falsch.
Ich meine nicht den Fakt (das weis ich gar nicht) sondern die Herangehensweise.
Lesbarkeit des Codes hat erstmal Vorrang. Optimierungen auf diesem Niveau werden erst dann (auf kosten der Lesbarkeit) gemacht, wenn dies *nachweislich* Ursache des Flaschenhalses war. (üblicher Weise ist es das nicht).

Problematisch ist der häufige Zugriff auf Variablen fremder Objekte trotzdem: es ist idR. ein Verstoß gegen die OO-Prinzipien...



Civilazi hat gesagt.:


> Also kein Optimieren auf der Algorithmenebene, sondern schon tiefer.


Aber optimierung des Algorithmus wird immer mehr bringen, als der JVM mal einen Sprung zu ersparen...



Civilazi hat gesagt.:


> Ich möchte mir kein Profiling sparen, sondern habe gedacht, dass es evtl. schon während des Implementierens eben performante und nicht so performante Wege gibt, Dinge zu erledigen.


Nutze die richtigen Klassen der API z.B.: [JAPI]StringBuilder[/JAPI] zum Zusammenbau von Texten  in Schleifen, [JAPI]ArrayList[/JAPI] oder [JAPI]Hashset[/JAPI] statt [STRIKE][JAPI]Vector[/JAPI][/STRIKE]...



Civilazi hat gesagt.:


> Ich verfolge natürlich trotzdem das Ziel, gut lesbaren Code zu schreiben.
> Gibt es solche Tips oder war das nur früher mal aktuell und man sollte die VM einfach machen lassen oder wie sieht es hier aus?


Im wesentlichen heist die Devise: Vermeide unnötige Schleifen und an sonsten lass die Hotspot-VM ihren Job machen.

bye
TT


----------



## Civilazi (16. Jan 2013)

Vielen Dank für die Buchtips, werde ich mir auf jeden Fall anschauen. 

Der Hintergrund meiner Frage ist der, dass es um die Implementierung von schon vorhandenen Algorithmen geht - z.B. bei mir aktuell der Ford-Fulkerson zur Bestimmung eines minimalen Schnittes in einem Netzwerk. Das heißt, der Algo ist "fertig", Aufwand in O-Notation steht fest, außerdem ist klar, wie er funktioniert. Daran soll auch nichts geändert werden.
Er muss eben "nur" noch schnell sein, durchaus auch auf Kosten der Lesbarkeit, auch wenn ich es immer noch objektorientiert haben möchte. 

Daher die Frage nach solch low-lvl-Techniken. Kennt da jemand mehr? Oder sogar Bibliotheken mit schnelleren Collections o.ä.?
Mit der normalen API kenn ich mich mittlerweile ganz gut aus. Trotzdem danke auch für die Tips.


----------



## tfa (16. Jan 2013)

nillehammer hat gesagt.:


> - Unnötige Objekterzeugung


Vorsicht mit diesem Tipp. Unnötige Objekterzeugungsvermeidung (z.B. durch überflüssiges Objekt-Pooling) kann schädlich sein für die GC-Performance. Viele sehr kurzlebige Objekte zu erzeugen (in minimalem Scope) ist recht billig.



> - String-Konkatenierung mittels des '+'-Operators


Wenn diese in einer Schleife stattfinden. Sonst ist nichts dagegen einzuwenden.


----------



## nillehammer (16. Jan 2013)

> Der Hintergrund meiner Frage ist der, dass es um die Implementierung von schon vorhandenen Algorithmen geht - z.B. bei mir aktuell der Ford-Fulkerson zur Bestimmung eines minimalen Schnittes in einem Netzwerk. Das heißt, der Algo ist "fertig", Aufwand in O-Notation steht fest, außerdem ist klar, wie er funktioniert. Daran soll auch nichts geändert werden.
> Er muss eben "nur" noch schnell sein, durchaus auch auf Kosten der Lesbarkeit, auch wenn ich es immer noch objektorientiert haben möchte.


Ich kenne den Algorithmus leider nicht. Aber, da Du anscheinend schon Code hast, kannst Du diesen Posten? Kann man ja mal drüber schauen, ob er unnötige Schleifendurchläufe, Methodenaufrufe, Objekterzeugung oder sowas enthält.


----------



## nillehammer (16. Jan 2013)

tfa hat gesagt.:
			
		

> Vorsicht mit diesem Tipp. Unnötige Objekterzeugungsvermeidung (z.B. durch überflüssiges Objekt-Pooling) kann schädlich sein für die GC-Performance. Viele sehr kurzlebige Objekte zu erzeugen (in minimalem Scope) ist recht billig.


Wollte den Tipp auch nicht als Plädoyer für Pools verstanden wissen. Ich dachte da z.B. an annonyme Implementiereungen von Listenern/Comparatoren o.ä. Es gibt viel Code (auch viele Beispiele im Internet), wo *innerhalb einer Methode* new Comparator {...}, new xyzListener{...} etc. mit entspr. Implementierung der Methoden gemacht wird. D.h. es wird hier bei jedem Aufruf der Methode ein neues Objekt erzeugt, dass genau das gleiche macht, wie die zig Objekte vorher. Obwohl man es auch ein einziges Mal erzeugen und irgendwo hinlegen könnte, um es immer wieder zu verwenden.


			
				tfa hat gesagt.:
			
		

> [..]Zu Stringkonkatenierung mit +:
> Wenn diese in einer Schleife stattfinden. Sonst ist nichts dagegen einzuwenden.


Echt? Das wäre mal tatsächlich was Neues für mich. Die beiden folgenden Zeilen wären performancemäßig also äquivalient?

```
public String buildKeyValueOutput(String keyName, String value) {

 // + -Operator
 return keyName + "=" + value;

 // oder doch besser StringBuilder
 return new StringBuilder().append(keyName).append("=").append(value).toString();
}
```


----------



## tfa (16. Jan 2013)

> Echt? Das wäre mal tatsächlich was Neues für mich. Die beiden folgenden Zeilen wären performancemäßig also äquivalient?


Richtig. Der Compiler wandelt die Stringkonkatenation in nichts anderes als StringBuilder.append-Aufrufe um.

Diese Methoden

```
public String concat(String keyName, String value) {
		return keyName+"="+value;
	}

	public String builder(String keyName, String value) {
		return new StringBuilder().append(keyName).append("=").append(value).toString();
	}
```
ergeben diesen Bytecode:


```
public java.lang.String concat(java.lang.String keyName, java.lang.String value);
     0  new java.lang.StringBuilder [16]
     3  dup
     4  aload_1 [keyName]
     5  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [18]
     8  invokespecial java.lang.StringBuilder(java.lang.String) [24]
    11  ldc <String "="> [27]
    13  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    16  aload_2 [value]
    17  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    20  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33]
    23  areturn      
  
  // Method descriptor #15 (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
  // Stack: 2, Locals: 3
  public java.lang.String builder(java.lang.String keyName, java.lang.String value);
     0  new java.lang.StringBuilder [16]
     3  dup
     4  invokespecial java.lang.StringBuilder() [41]
     7  aload_1 [keyName]
     8  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    11  ldc <String "="> [27]
    13  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    16  aload_2 [value]
    17  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    20  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33]
    23  areturn
```


----------



## nillehammer (16. Jan 2013)

> Richtig. Der Compiler wandelt die Stringkonkatenation in nichts anderes als StringBuilder.append-Aufrufe um.


Das wusste ich. Ich dachte nur, dass er für *jedes* '+' einen neuen erzeugt. Das hast du mit Deinem Bytecode ja eindrucksvoll widerlegt. Kann leider nur einmal "Danke" klicken


----------



## ARadauer (16. Jan 2013)

Bei schleifen muss mann aufpassen. Da empfielt es sich auf jedenfall den string builder einzusetzen


----------



## Civilazi (16. Jan 2013)

nillehammer hat gesagt.:


> Ich kenne den Algorithmus leider nicht. Aber, da Du anscheinend schon Code hast, kannst Du diesen Posten? Kann man ja mal drüber schauen, ob er unnötige Schleifendurchläufe, Methodenaufrufe, Objekterzeugung oder sowas enthält.



Sehr gern morgen, wenn ich wieder in der Uni bin. Das Ziel ist aber nicht nur, diesen Code schnell zu bekommen, sondern auch allgemeine Richtlinien / Wissen zu haben. Davon scheinen die empfohlenen Bücher viel zu bieten


----------



## FArt (16. Jan 2013)

"More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason — including blind stupidity." — W.A. Wulf



Civilazi hat gesagt.:


> teilweise extrem wichtig


 ... interessant...

Gut waren die Tipps nach "Clean Code" und "Effecitve Java". Danke an tfa.


----------



## Civilazi (17. Jan 2013)

"premature optimization is the root of all evil" - Donald Knuth. 

... hilfreich...

Nichtsdestotrotz gab es hier schon gute Tips, ich lade nachher gern Beispielcode hoch. Ich möchte mich wie gesagt nicht ums Profiling drücken, sondern einfach best practices für performanten Code kennenlernen.


----------



## Bleiglanz (17. Jan 2013)

Meine Tipps:

1) Das Buch von Bloch
2) Lernen was in Java NICHT zu erhöhter Performance führt obwohl es so aussieht
3) Standardtechniken verwenden, z.B. Loop unrolling ? Wikipedia und andere

und

zuerst mit einem korrekten, eleganten Programm anfangen; Performance bei 'kleinen Problemen' analysieren und erst dann mit einem Profiler prüfen, wann/wo bei 'großen Problemen' überhaupt Performanceprobleme auftauchen.

Auf keinen Fall im Vorfeld wild 'ins Blaue' irgendwelche abstrusen Optimierungen machen, die möglicherweise überhaupt nichts bringen. Ist Zeitverschwending.


----------

