Anwendungen

Java-Anwendungen im Überblick

Eines der am schwersten auszurottenden Gerüchte ist die Mär der mangelnden Performance bei Java-Anwendungen. Oberflächlich betrachtet ist Java zwar eine interpretierte Sprache, aber das stimmt im Hintergrund schon lange nicht mehr. Weltweit sind wohl die meisten serverseitigen Enterprise-Anwendungen inzwischen in Java programmiert und daß all diese Anwendungen trotz mangelhafter Performance enstanden sein sollen, ist schon im Grundsatz eine sehr zweifelhafte Annahme. Java Anwendungen sind nach dem ersten Durchlauf genauso compiliert wie Anwendungen in C oder C++ - und werden zusätzlich laufend an den von der Laufzeitumgebung ermittelten Hotspots optimiert.

Was viele Enthusiasten der maschinennahen Programmierung nicht beachten ist die Tatsache, daß die Performance eines C-Programmes zum einen davon abhängt mehr oder weniger unleserliche und schwer wartbare, dafür aber fehleranfällige Konstrukte zu verwenden und potentielle Speicherlecks im Dutzend zu produzieren und zum anderen von der Qualität der Laufzeitbibliotheken. Bei der Objekterzeugung ist Java heute schon um Größenordnungen schneller als beispielsweise C++, was unter anderem damit zusammenhängt, daß keine Kompatibilität zu 20-30 Jahre alten Programmen bestehen muß. Da der Progammierer nicht direkt auf den Speicherort einer Methode oder eines Objektes zugreifen kann (und dies auch gar nicht will, da es unnötig ist), muß die Implementierung keine Rücksicht auf gängige Entwurfsmuster in maschinennahen Programmiersprachen nehmen.

Auf der Client-Seite liegen die Dinge ein wenig anders. Viele Performanceprobleme bei Java-Desktopanwendungen liegen eher am Design des Programmes, als an Spracheigenschaften. Als multithreadingfähige, objektorientierte Programmiersprache mit einem ausgeklügelten Exception- und Eventmodell ist Java nicht sehr gut für Programmentwürfe geeignet, die in einer großen Schleife und in einem einzigen Thread arbeiten. Außerdem sind die von C bekannten "Optimierungen" in Java nicht sehr gut, da sie die Arbeit des Optimierers oft behindern und daher eher zu mangelhafter als zu besserer Performance führen. In C und teilweise C++ gibt es für jeden Compiler einen relativ direkten Zusammenhang zwischen Programmcode und erzeugtem Maschinencode. Das Aufrollen von Schleifen und ähnliche Dinge sind also je nach Anwendung unter Umständen sinnvoll. Bei Java nicht. Selten benutzte Programmteile werden nicht aufwendig optimiert, während häufig benutzte mit einer ganzen Reihe aggressiver Optimierungen beschleunigt werden.

Eine ganz einfache Technik um die "gefühlte Geschwindigkeit" einer Java-Deskto-Anwendung zu erhöhen besteht darin, für funktionale Gruppen auch jeweils eigene Threads zu verwenden. Wenn die Swing-Oberfläche in einem eigenen Thread läuft und aufwendige I/O-Operationen oder Berechnungen in jeweils einem anderen, ist eine Swing-Oberfläche genauso schnell wie eine native. Es ist nicht die Geschwindigkeit, die ein schlecht programmiertes Java-Programm gefühlt langsam macht, wie man leicht an der Prozessor-und Speicherauslastung feststellen kann, sondern die Tatsache, daß blockierende Ereignisse und Oberflächenereignisse im gleichen Thread laufen.

Aber Performance als reine Geschwindigkeit betrachtet ist ohnehin nur ein immer unwichtiger werdender Aspekt. Heutige Computer sind von ihrer Geschwindigkeit her kaum auszulasten und die Preise für Speicher und Festplatten fallen auch kaum noch ins Gewicht. Wichtiger als diese einmaligen Kosten sind heute die laufenden Kosten, da Programmiererstunden und Verluste durch Ausfallzeiten sich sehr schnell zu einem Vielfachen des Hardwarepreises addieren. Java und die im Java-Biotop entstandenen Klassenbibliotheken sind von Grund auf für verteilte und hoch skalierbare Lösungen in heterogenen Netzwerken ausgelegt. Da pure Java-Anwendungen grundsätzlich keine Abhängigkeiten zur zugrundeliegenden Hardware haben und lediglich auf eine standardkonforme JVM angewiesen sind, sind sie ohne weitere Arbeit auf eine andere Hardwareplattform portierbar, was z.B. die Serverkonsolidierung einfacher und kostengünstiger macht. Sie skalieren in der Regel sehr gut und wenn einmal die Performance eines Servers nicht mehr ausreicht kann man mit wenig Aufwand mehr Hardware hinzufügen, was erheblich billiger ist, als eine zumindest teilweise hardwareabhängige Anwendung in einer anderen Programmiersprache auf mehr oder gar eine ganz andere Hardware anzupassen.

Letztlich sind diese ganzen Diskussionen um Performance und TCO aber eher ideologischer Natur. Vom pragmatischen Standpunkt aus sind die meisten Unterschiede marginal und man sollte einfach das Werkzeug wählen, welches man am besten beherrscht oder welches den Job am besten erledigt.

Share/Save