PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Technische Frage zur Performance von Bytecode-Sprachen


Gast
2010-03-01, 15:33:31
Hallo!

Man kennt ja die üblichen Geschichten über die Langsamkeit von Java und alles drum herum.

Der Hauptgrund hierfür dürfte ja sicherlich die Interpretierung des erzeugten Bytecodes sein, welcher auf der Zielmaschine erst noch in Maschinencode umgewandelt werden muss, richtig? Dann gibt es auch noch den Garbage Collector, aber da dieser ja nicht 24/7 am arbeiten ist können wir den erstmal außen vor lassen.

Auf was ich jetzt eigentlich hinaus will: Wir haben zur Laufzeit also Maschinencode (C/++ und Co.) vs. Interpretation von Bytecode (Java eben, C# etc..).
Was machen jetzt Java, C# usw. aber mit Programmteilen, welche bei der Laufzeit in Maschinencode umgewandelt wurden und später wieder zum Einsatz kommen? Greifen die Virtual Machines dann auf den bereits erzeugten Maschinencode zurück, oder geht das mit der Interpretation wieder von vorne los?

Dass alles wieder von vorne losgeht kann ich mir fast nicht vorstellen, "man hat sich die Arbeit doch bereits gemacht".
Falls aber auf den bereits erzeugten Code zurückgegriffen wird verstehe ich nicht, warum Java und vergleichbare Sprachen ab diesem Zeitpunkt langsamer sein sollten als C/++ u.a.

Klar, das Starten eines Java-Programms ist träger, eben wegen dieser ganzen Interpretation. Was passiert aber ab dem Zeitpunkt, ab dem jeder Teil des Java-Programms schonmal interpretiert wurde? Müsste man ab dann nicht die selbe Geschwindigkeit wie C/++ erreichen?

Mehr steckt hinter meiner Frage eigentlich garnicht. Ich frage mich folglich nur was denn im weiteren Verlauf passiert, wenn die nervige Interpretation nun abgeschlossen ist.

Danke!


PS: Falls es da übrigens nennenswerte Unterschiede zwischen Java und C# gibt, bin an beidem interessiert :)

Trap
2010-03-01, 17:20:34
Es wird im Normalfall nichts mehrfach in Maschinensprache übersetzt, sondern der bereits generierte Code wird direkt aufgerufen.

Die VM-Sprachen schneiden in Vergleichstests etwas schlechter ab, weil die Programme mehr machen (Fehlerprüfung wie null, Arrayoverflow, casts, GC), die JIT-Compiler noch nicht ganz so gut optimiert sind wie die Compiler für C/C++ und ein paar berechnungsintensive Optimierungsmethoden weggelassen werden.

Der Unterschied zwischen Java und C++ ist nicht unbedingt größer als zwischen C++ mit guten und schlechten Compilern.

Monger
2010-03-01, 17:56:39
Wie Trap schon gesagt hat: dass interpretierte Sprachen langsam sind, ist pauschal quatsch.

Wie du schon selber richtig erkannt hast: ist der Maschinencode einmal kompiliert (und moderne Compiler sind sehr, SEHR schnell. Da ist das Laden des Quellcodes von Festplatte weit langsamer als der Compilevorgang), liegt er im Speicher, und man kann jedesmal darauf zugreifen.

Theoretisch sind "interpretierte" Sprachen wie Java oder .NET sogar schneller als fertige Kompilate, weil sie Optimierungen auf der Zielplattform vornehmen können. Bei kompilierten Programmen packt man allenfalls zwei, drei verschiedene Varianten auf die CD drauf (was auch regelmäßig ein Deployment Alptraum ist), und packt dann beim Setup die richtige Variante drauf. Was dann passiert wenn man Hardware Komponenten tauscht... naja, kann sich jeder denken.

Praktisch gesehen stehen da andere Probleme im Weg. Ich kann mich z.B. daran erinnern, dass Javas Bibliothek für Grafikfunktionen (AWT) ziemlich schwerfällig ist, weil sie aus Gründen der Plattformunabhängigkeit ihre eigenen Fenster zusammenstricken, statt die Windows Forms o.ä. zu benutzen. Ich hab auch mal gehört, dass die angeblich bei der Interprozesskommunikation einen Engpass hatten, weil sie halt nur in Klartext kommuniziert haben...

Bei .NET weiß ich, dass die Kommunikation mit COM Komponenten (die nunmal in der Windowswelt noch sehr häufig sind) relativ träge ist. Sobald man sich ausschließlich in der .NET Welt bewegt, geht das alles normalerweise enorm schnell.


Sprich: unausgereifte Compiler, verbuggte Programmbibliotheken und ein paar Features die Performance zugunsten von mehr Robustheit opfern sind der Grund für schlechte Performance - und nicht etwa, dass das interpretierte Sprachen sind.

Ganon
2010-03-01, 22:26:08
Der Hauptgrund hierfür dürfte ja sicherlich die Interpretierung des erzeugten Bytecodes sein, welcher auf der Zielmaschine erst noch in Maschinencode umgewandelt werden muss, richtig?

Nein, und da das schon nicht stimmt, stimmt auch der Rest des Textes nicht. ;)

Es sind Hauptsächlich folgende Dinge, die VM-Sprachen "langsamer" machen:

- Garbage Collector -> periodisch muss der gesamte (OK, nicht der ganze, aber das ist alles ziemlich komplex) Programmspeicher durchwühlt werden
- Speicherbereichsprüfung -> bei jedem Array-Zugriff werden aus Sicherheitsgründen die Bereiche geprüft

Was "Java" abseits der oben genannten Punkte "langsamer" macht:

- die GUI-Bibliothek malt aus Plattformunabhänigkeitsgründen ALLES alleine
- Intensive Nutzung von Reflections in so ziemlich allen großen Bibliotheken

Ich habe "langsamer" bewusst in Anführungszeichen geschrieben. Denn unterm Strich macht sich das bei "normalen" Anwendungen überhaupt nicht bemerkbar. Bei Java7 wird afaik sogar die Speicherprüfung mit einem neuen System fast komplett umgangen.

Und in C# werden sogar Spiele programmiert, also kann's gar nicht zu langsam sein ^^

Gnafoo
2010-03-01, 22:49:38
.NET muss übrigens nicht zwangsweise auch JIT-Compiler heißen. Es gibt in .NET einen ahead-of-time-Compiler namens NGEN (Native Image Generator), der z.B. während der Installation nativen Code erzeugen und in einem Cache ablegen kann. Beim Programmstart wird dann darauf zurückgegriffen.

Man kann soweit ich weiß auch bei der Installation die Kompilierung in nativen Code anfordern, so dass diese später ausgeführt wird, wenn der Rechner ohnehin gerade untätig ist. Das macht dann der "Microsoft .NET Framework NGEN"-Service, der irgendwo in der Liste der Dienste auftaucht.

Ob er beim JIT-kompilieren den nativen Code auch im Cache ablegt und über mehrere Programmstarts hinweg wiederverwendet weiß ich nicht genau. Ich glaube allerdings, dass man es explizit per NGEN erzwingen muss. Wenn man mal per Google nach NGEN sucht, findet man einiges dazu.

Coda
2010-03-02, 03:05:22
und moderne Compiler sind sehr, SEHR schnell.
Das stimmt so nicht. Es gibt Optimierungsroutinen die Ewigkeiten brauchen. Solche werden bei einem JITC halt einfach nicht gemacht. Managed Code ist bei realistischen Algorithmen von ein wenig bis 3x langsamer als Native Code.

Wobei so Dinge wie Stringverarbeitung bei naivem C++-Code (addiere 100.000 Strings) langsamer sind als der gleiche naive C#-Code, weil dort der Compiler intelligenter vorgehen kann. Auch Speicher-Allozierung/Deallozierung ist bei Managed Code um Magnituden schneller, da muss man bei Native Code aufpassen wo man solche macht. Pick your poison.

Und in C# werden sogar Spiele programmiert, also kann's gar nicht zu langsam sein ^^
"Spiele" ist ein sehr breites Feld. Das meiste ist heute sowieso GPU bound. Wenn man wirklich anspruchsvolles Zeug auf der CPU macht, dann wird man dort auch keinen managed code mehr einsetzen.

Aber Managed Code wäre für 99% des Codes der in Umlauf ist wohl die deutlich bessere Wahl als C++. Ich verstehe schon allein nicht warum man Browser als Sicherheitslücke No. 1 in Native-Code-Sprachen entwickelt.

.NET muss übrigens nicht zwangsweise auch JIT-Compiler heißen. Es gibt in .NET einen ahead-of-time-Compiler namens NGEN (Native Image Generator), der z.B. während der Installation nativen Code erzeugen und in einem Cache ablegen kann. Beim Programmstart wird dann darauf zurückgegriffen.
Der macht allerdings genau das gleiche an Optimierungen wie der JITC. Warum auch immer.

Shink
2010-03-02, 08:01:31
Aber Managed Code wäre für 99% des Codes der in Umlauf ist wohl die deutlich bessere Wahl als C++. Ich verstehe schon allein nicht warum man Browser als Sicherheitslücke No. 1 in Native-Code-Sprachen entwickelt.
Die Sache mit dem Browser ist mir ebenfalls absolut unklar; vor allem bei Microsoft. Die müssen ja wirklich nur für Systeme entwickeln für die ein .NET-Framework verfügbar ist.

.NET muss übrigens nicht zwangsweise auch JIT-Compiler heißen. Es gibt in .NET einen ahead-of-time-Compiler namens NGEN (Native Image Generator), der z.B. während der Installation nativen Code erzeugen und in einem Cache ablegen kann. Beim Programmstart wird dann darauf zurückgegriffen.
Für Java gibt es da Excelsior Jet. Der ist wirklich sehr schnell. Sobald man aber etwas wirklich interessantes macht (z.B. Reflection, Classloader-Überschreibung o.ä.) ist der Performancegewinn wieder im Eimer. Gerade AWT oder Swing wird aber ziemlich beschleunigt damit. (Naja, zumindest traf das auf mein AWT-Tetris zu;D)

Ich kann mich z.B. daran erinnern, dass Javas Bibliothek für Grafikfunktionen (AWT) ziemlich schwerfällig ist, weil sie aus Gründen der Plattformunabhängigkeit ihre eigenen Fenster zusammenstricken, statt die Windows Forms o.ä. zu benutzen.
AWT verwendet AFAIK tatsächlich Windows Forms. Allerdings verwendet quasi niemand AWT da man damit keine ordentlichen GUIs stricken kann.
Swing malt hingegen tatsächlich alles selber. Erstaunlicherweise ist auch das schneller als man erwarten würde. Allerdings sind die Reaktionszeiten minimal höher und bei GUIs spürt man das ordentlich.

Ist aber kein Java-Problem. Es gibt wirklich lahme Sprachen mit denen man schnelle GUIs machen kann (z.B. alte VB-Versionen) und umgekehrt auch in C oder C++ geschriebene Software deren GUI sich träger anfühlt als eine Swing-Anwendung. Man vergleiche z.B. das in C++ geschriebene Open Office 2 mit dem in Swing geschriebenen ThinkFree Office.

Ganon
2010-03-02, 08:42:16
Ich denke mal das mit dem Browser ist historisch gewachsen. IE, Gecko und WebKit haben ja alle C/C++ Vorgänger und bis auf den IE wollen alle Engines überall laufen. Und welche Managed-Sprache außer Java läuft auf allen Systemen gut (Mono krankt z.B. unter OS X noch)?

Und bei Microsoft denke ich, dass man da sogar schon was in Arbeit hat.

Monger
2010-03-02, 09:38:08
AWT verwendet AFAIK tatsächlich Windows Forms. Allerdings verwendet quasi niemand AWT da man damit keine ordentlichen GUIs stricken kann.
Swing malt hingegen tatsächlich alles selber.

Ist schon ein paar Jahre her dass ich was mit Swing gemacht habe, aber damals baute Swing auf AWT Funktionen auf. Wohl nur sehr weit unten an der Basis, aber eben doch.
Ich glaub, SWT war nochmal was sehr eigenes, aber das verwendet wohl wirklich niemand mehr.

Ganon
2010-03-02, 10:02:12
Ist schon ein paar Jahre her dass ich was mit Swing gemacht habe, aber damals baute Swing auf AWT Funktionen auf. Wohl nur sehr weit unten an der Basis, aber eben doch.

Swing baut wirklich immer noch auf AWT auf. AWT ist alles der Satz an Klassen, der von der VM plattformspezifisch implementiert werden muss. Dies betrifft aber im Endeffekt für Swing nur die Low-Level-Funktionen wie die Grafik-Schnittstelle Graphics. Unter Linux wird AWT eben mit X11 implementiert, unter Windows mit der WinAPI und unter OS X eben mit Cocoa.


Ich glaub, SWT war nochmal was sehr eigenes, aber das verwendet wohl wirklich niemand mehr.

Naja, doch. Alles was mit Eclipse zu tun hat, verwendet SWT. Aber die Vorteile von SWT schrumpfen immer weiter. Performance ist es schon lange nicht mehr. Der Vorteil von SWT ist heutzutage eher, dass sich die Komponenten "nativer" verhalten. Dafür hat man den "Stress" immer native dlls/sos/dylibs mitliefern zu müssen.

Der_Donnervogel
2010-03-02, 15:44:00
PS: Falls es da übrigens nennenswerte Unterschiede zwischen Java und C# gibt, bin an beidem interessiert :)Ich meine mich dunkel zu erinnern, dass es einen Unterschied gibt wann wie viel Code übersetzt wird. Die eine Sprache übersetzt gleich beim Laden größere Codeblöcke (Klassen?) auf Verdacht, während die andere nur das übersetzt was sie wirklich braucht. Hat beides Vor- und Nachteile. Vielleicht weiß ja einer hier mehr, oder ob das überhaupt noch State of the Art ist.
Swing baut wirklich immer noch auf AWT auf.Ich glaube das wird sich auch nicht (so schnell) ändern. Man braucht sich nur die Vererbungshierarchie der Swing-Klassen anschauen. Da kommt sehr oft zumindest ein java.awt.Component vor. Die ganzen Swing-Klassen wie JFrame, JButton, usw. erben alle von AWT-Klassen.

Shink
2010-03-02, 21:20:49
Ist schon ein paar Jahre her dass ich was mit Swing gemacht habe, aber damals baute Swing auf AWT Funktionen auf. Wohl nur sehr weit unten an der Basis, aber eben doch.
Meinte ich eigentlich auch: AWT verwendet Forms etc direkt. Swing verwendet einen ganz kleinen Teil von AWT - den verwendet es dazu die ganzen GUI-Elemente per Vektor/Bitmapgrafik zu malen. Also ist z.B. ein AWT-Button tatsächlich ein nativer Button, während ein Swing-Button einfach ein Bild auf einem nativen (AWT-)Fenster ist.

Ich glaub, SWT war nochmal was sehr eigenes, aber das verwendet wohl wirklich niemand mehr.
SWT hat wieder ein etwas anderes Konzept: Prinzipiell verwendet es wie auch AWT native Komponenten. Während es bei AWT aber die Vorgabe gibt "eine Java-Implementierung verwendet verschiedene plattformspezifische Libraries" heißt es bei SWT "eine Java-Implementierung pro plattformspezifischer Library". Naja, außerdem ist die API natürlich ganz anders: Im Gegensatz zu AWT und Swing achtet man auf Vermeidung von Vererbung und versucht nicht mit allen Vorgängerversionen kompatibel zu sein.
Prominente SWT-Anwendungen sind Eclipse, Lotus Symphony, Lotus Notes, Vuze (Azureus).

Yavion
2010-03-02, 22:31:48
Das stimmt so nicht. Es gibt Optimierungsroutinen die Ewigkeiten brauchen. Solche werden bei einem JITC halt einfach nicht gemacht. Managed Code ist bei realistischen Algorithmen von ein wenig bis 3x langsamer als Native Code.


Könnte man das Problem durch einen Umstieg auf eine neuere Systemarchitektur umgehen oder ist das einfach ein prinzipielles Problem, dass bei der Übersetzung von einer Hochsprache in einen beliebigen Maschinencode auftritt?

Aquaschaf
2010-03-05, 10:19:52
Könnte man das Problem durch einen Umstieg auf eine neuere Systemarchitektur umgehen

Mit Systemarchitektur hat das nichts zu tun. Registerallokation, d.h. Code zu erzeugen der mit einer möglichst geringen Menge an Speicherzugriffen auskommt, ist beispielsweise prinzipiel ein schwieriges Problem für das es unterschiedlich aufwändige heuristische Lösungsverfahren gibt. Und so lange es dabei bleibt dass Speicher entweder groß und langsam, oder klein und schnell sein kann wird dieses Optimierungsproblem relevant sein. Bei JITC nimmt man unter Umständen einfachere Verfahren um die compile-Zeit kurz zu halten.

Prinzipiell können JITC und Interpretation aber auch Vorteile für die Performance haben. Der Compiler hat mehr Informationen über das System auf dem der Code läuft und eventuell auch über den tatsächlichen Kontrollfluss im Code.