Micro-Optimierung — bringt das immer was?

Irgendwas ist ja immer, heute Micro-Performance-Optimierung.

Man ließt immer mal wieder von den coolen Jungs, die mal wieder einen super schnellen Implementierung einer HashMap oder einer anderen JDK-Funktion implementiert haben. Wenn sie gut sind, haben sie ihre Performance Messungen auf unterschiedlichen Rechnern durchgeführt. Am besten noch mit JMH, einem für diese Zwecke speziell entwickeltes Framework — ich muss sagen, eine echt cooles Spielzeug, wenn man so etwas mag.

Ich muss zugeben, ich habe mich der Micro-Optimierung auch schon das eine oder andere mal hingegeben (als Fingerübung 🙂 ) um mich dann am Ende zu fragen: was hat das jetzt wirklich gebracht? Was sagen mir die Zahlen: vorher 163.840 Operationen pro Sekunden und nach der Optimierung, waren es 819.200 — Hammer — Faktor 5 — was für sind wir nicht für geiler Programmierer, oder? Aber was hat diese Optimierung für Auswirkungen auf mein Programm? Laufen meine Algorithmen jetzt 5 mal schneller? Wenn man die meisten Micro-Optimierungs-Blog-Artikel ließt glaubt man das sofort.

Als Beispiel nehmen wir eine Anwendung, die Dokumente erzeugt und wir die Operation für das Schreiben von Tags/Elementen wie oben erwähnt optimiert haben. Jedem ist sicherlich sofort klar, das wir jetzt nicht auf ein mal 5 mal mehr Dokumente verarbeiten können — noch wird das Erzeugen eines Dokuments 5 mal schneller sein.
Der erste Ansatz ist, die eingesparte Zeit pro einem mittel großen Dokuments zu berechnen. Bei einer Tag-Größe von 64 Zeichen und einer Dokumenten Größe von 1 MB benötigen wir 16.384 Operationen. Dann haben wir bei dieser Dokumenten-Größe sage und schreibe 0,08 Sekunden gespart — sofern ein Dokument von einem Thread bearbeitet wird. Ehrlich, da habe ich mir bei einem Faktor 5 ein bisschen mehr vorgestellt.

Beim zweiten Ansatz möchten wir wissen, wieviel mal man die Operation ausführen muss um eine Sekunde (eine Minute) an Laufzeit zu sparen — wir drehen den Spieß um. In unserem Fall sparen wir eine Sekunde bei 204.800 Ausführungen und für eine Ersparnis von einer Minuten müssten wir über 12 Millionen Tags schreiben oder umgerechnet 750 Dokumente. Das ganze lohnt leider nicht wirklich, denn die besagte Anwendung erzeugt pro Tag vielleicht mal 10 Dokumente.

Es gibt gerade wieder ein paar Performance Artikel im Eclipse Umfeld für die EclipseCollections. Wenn ich dort dann lese, dass das JDK 1 mio ops/s macht und die Eclipse Implementierung 3 mio op/s bin auch ich schwer beeindruckt. An dieser Stelle würde mich viel mehr interessieren, welche Auswirkungen das auf einen Full-Build hat oder für das Editor-Feeling. Um eine Sekunde schneller zu werden, braucht es 1,5 Mio Operations und für ne Minute 90 Mio pro Thread — kommt da ein Full-Build dran? Viel spannender würde ich es finden, wenn diese Optimierung es in eines der nächsten JDKs schaffen würden.

Weiter geht es mit if-else/for/while Optimierung um auch noch das letzte Stück Performance aus dem Code zu holen. Meistens ist er nach der Optimierung nicht mehr so gut lesbar, dafür konnte man aus 15 Mio 21 Mio Operationen pro Sekunde machen. Doof ist nur, das die Methode optimistisch 1 Mio mal pro Tag aufgerufen wird — wir brauchen aber 52 Mio Aufrufe um eine Sekunde zu sparen. Da Optimiere ich doch lieber den Code bei if/else zum besseren Verstehen und spendiere einer while Schleife einen extra Method-Call um diese hässlichen while ((line = reader.readLine()) != null) zu vermeiden.

In diesem Sinne happy coding.