Java-Performance #

Immer wieder beim Programmieren bin ich auf Bereiche gestossen, wo es nötig war, die normalen Grenzen der Möglichkeiten der Sprache Java auszuloten und unter Umständen ein wenig zu verschieben. Leider waren das immer sehr spezielle Probleme mit sehr speziellen Lösungen (wie ich jeweils dachte). Deshalb habe ich mir dazu nicht viel gemerkt geschweige denn dokumentiert. Das möchte ich hiermit ändern und eröffne diese Seite als Anlaufpunkt und Linksammlung zu verschiedenen Themen rund um die "Performance" von Java-Programmen. Ich denke, daß sie im Laufe der Zeit wachsen wird. -- ThomasBayen

Swing #

Bei Swing ist es klassische so, daß das gesamte Programm inklusive aller GUI-Operationen im EDT (Event Dispatch Thread) ausgeführt wird. Dadurch wird die GUI natürlich verlangsamt bzw. "friert ein", wenn das Programm irgendwelche längeren Operationen durchführt. Dies erzeugt beim Benutzer das unbefriedigende Gefühl, das gesamte Programm wäre langsam, obwohl er eigentlich nur die Reaktion der GUI damit meint.

Die Lösung hierzu ist JavaMultithreading und auf dieser Seite beschrieben. Die einfache Antwort ist die Benutzung der Klasse SwingWorker, aber auch das öffnet bereits die Büchse der Pandora, wenn man im zweiten Thread auf Daten des restlichen Programms zugreifen will. Wer sowas auf sich zukommen sieht, sollte am besten vorne herein daran denken. Eigentlich sind die Änderungen gar nicht so schmerzhaft, wenn man sie nicht im nachhinein in ein bestehendes Programm hineinwursteln muss.

Swing remote #

Benutzt man Swing auf einem entfernten X-Server, so ist die Performance teilweise um Größenordnungen kleiner. Ich habe die Probleme (und Lösungen) noch nicht komplett durchdacht, sammle hier aber schon mal Links zum Thema

Grafik / 3D-Grafik #

Auf der Seite JavaGrafik haben wir bereits einiges zum Thema gesammelt.

Speicherlecks #

Entgegen der weitläufig verwendeten Theorie, daß die Garbage Collection in Java Wunder vollbringen könnte, kann man auch in Java durchaus Speicher verlieren. Im Grunde handelt es sich dabei um Objekte, die nicht mehr benutzt werden, aber noch irgendwo referenziert werden. Gerade bei komplexen Datenstrukturen, die aufeinander verweisen sowie bei der Swing-Programmierung mit Listenern habe ich größte Probleme damit gehabt. Da ich diese Probleme noch nicht zufriedenstellend allgemeingültig gelöst habe, hier erstmal nur eine Liste von Gedanken und Links. Vielleicht mag ja jemand teilhaben und bei der Lösung helfen.

Lecks bemerken #

Ich würde als Endziel gerne einen Unittest(http://www.junit.org) erhalten, der feststellt, ob mein Programm Speicher verliert. Wenn ja, wäre es schön, wenn die "verlorenen" Objekte irgendwie als Hinweis ausgegeben werden könnten. Dazu stelle ich mir vor, daß mein Programm einmal ausgeführt wird, ein Speicherabbild genommen wird, dann mein Programm in derselben VM ein zweites Mal ausgeführt wird und die Differenz zum vorherigen Abbild festgestellt wird. Eine Differenz bedeutet dann ein Leck und müsste "von Hand" weiteruntersucht werden. -- ThomasBayen

Es gibt umfangreiche APIs zum Thema, aber nichts einfaches, was schnell hilft. Es gibt Klassen in "java.lang.Runtime", mit denen man den aktuell verbrauchten Speicher anzeigen kann. Da werden dann allerdings Objekte mitgezählt, die bereits freigegeben, aber noch nicht von der Garbage Collection aufgeräumt wurden. Mit "Runtime.gc()" kann man eine solche starten, es wird aber ausdrücklich nicht garantiert, daß dadurch alle Objekte auch wirklich aufgeräumt werden. Ist ja wie bei der Müllabfuhr in Neapel...

Etwas Licht ins Dunkel bringen die Klassen in Monitoring and Management API, z.B. im Paket "java.lang.management". Dort kann man etwas detailliertere Angaben bekommen. Insbesondere gibt es die Methode MemoryMXBean.getObjectPendingFinalizationCount(), die uns zwar immer noch nicht versprechen kann, daß eine GC auch durchgeführt wurde, dieses aber zumindest überprüfen könnte. Eine Liste von Objekten auf dem Heap ergibt sich aber leider hier auch nicht.

Die Möglichkeiten der Monitoring and Management API sind wohl zu Anfang am besten mit JConsole zu demonstrieren.

Die letzte Lösung könnte JPDA, die Debugging API sein. Dort ist es möglich, den Heap komplett auszulesen und dann z.B. mit einem vorherigen Programmlauf zu vergleichen. Leider muss man dazu das Programm komplett wie aus einem Debugger heraus in einer eigenen VM starten. Das macht erstens einigen Aufwand, bis es steht, dürfte zweitens recht langsam sein, wenn man für jeden Test eine neue VM startet, müsste drittens erstmal in JUnit-Testmethoden integriert werden und viertens schliesst das wohl aus, daß man diese Tests gleichzeitig mit dem Eclipse-Debugger bearbeiten kann.

Gerade letzteres erscheint mir als grosser Nachteil, weil der Sinn des Tests ja nur sein kann, Probleme im Nachgang mit dem Debugger besser verfolgen zu können.

Es gibt natürlich einige fertige Tools, die einem helfen, Fehlern auf die Schliche zu kommen. Ich verweise hier auf obengenanntes JConsole oder auch auf das Eclipse TPTP Plugin, mit dem ich einige Erfahrung habe und das ich empfehlen kann. Alle diese Tools haben aber den Nachteil, daß ich sie nicht öfters und automatisiert in Unittests einsetzen kann. D.h. ich bemerke ein Speicherleck meistens erst lange, nachdem ich es eingebaut habe, was die Suche enorm erschwert.

Links:

Dieser Artikel hat mich auf xtest gebracht, das vielleicht einer Lösung nahe kommt.

Tests in Tests

Eigentlich möchte ich nicht nur besondere Lecksuch-Tests schreiben, sondern im Grunde müsste man alle bereits vorhandenen Tests einmal durch einen Lecksuch-Metatest jagen. Nur dadurch würde man alle Aspekte des Programms testen können. Was ist dabei zu beachten?

Lecks vermeiden #

Gibt es gute Grundregeln, wie man Speicherlecks am besten vermeidet? Hierzu könnte wohl am besten jemand etwas sagen, der Erfahrung mit dem Debugging von ebensolchen hat. Also verschiebe ich das auf später.

-- ThomasBayen

Tags:  Java

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-6) was last changed on 30-Jun-2010 01:27 by ThomasBayen