Java ist schneller als C++!



  • byto schrieb:

    Die Statistik ist Deiner Meinung nach also nichtssagend, weil sie nicht auf Deine persönlichen Präferenzen zugeschnitten ist?

    Die Transferleistung, das auf die eigenen Präferenzen abzubilden, traue ich jedem zu.



  • Die Sache liegt wie immer im Detail:
    Ich habe C++ Code gesehen, da sage ich ganz klar:
    Java ist schneller. Da kann der Compiler noch so gut sein. Der Programmierer gibt ihm keine Chance (persönlich bin ich ja für eine Änderung des Compiliervorgehens). Den umgekehrten Fall gibt es auch. C++ kann Tricks, da kommt kein Java Compiler gegen an ( wie im aktuellen Projekt ).

    Aber schauen wie uns doch mal den JIT Compiler genauer an:
    In einer J2EE Umgebung wird der Code so ca. 600 mal interpretiert ausgeführt. Währenddessen sammelt der JIT ( wieso eingentlich JIT?) Profiler Informationen. In einem separaten Task wird dann der Code hoch optimiert übersetzt. (Interessanterweise wird Byte Code so gut wie gar nicht optimiert)

    Hat man genügend Prozessoren, fällt das nicht weiter auf. Sind jedoch alle CPUs belegt, fällt das massiv ins Gewicht. Genau wie mit dem RAM. In ner 8 GB Maschine als Desktop kann ein Mini-Java-Programm nicht auffallen. Wenn aber der ganze Desktop in Java geschrieben wurde, fällt das ganz massiv ins Gewicht.

    Das ist ja wie die Diskussion mit TCP oder UDP. Oder mit Verschlüsselung. Oder...
    Oder...
    Wenn ich eh Power im Überfluss habe, kann ich kaum Unterschiede messen.
    Interresant wird es erst, wenn die Kiste unter Dampf steht.

    Theoretisch + Ausblick:
    Die Compilerbauer, ob Java oder C oder C++ haben ja grundsätzlich dasselbe Vorgehen, so daß C oder Java Code auf binärer Basis gleich schnell laufen sollte.

    Java hat grundsätzlich die Nachteile:
    - Enormer Speicherverbrauch (Designbedingt, Cache is Speed!),
    - Ganz langsamer Aufstart

    C/C++ hat grundsätzlich die Nachteile:
    - Es baut und optimiert den Objectcode pro Datei, nicht pro Library. Da geht einem durch ungeschicktes Programmieren schon mal Faktor 10 ( in Worten: zehn ) verloren. Das ist eigentlich nur ein C++ Problem.
    - Wesentlich anspruchsvoller ( ich sag ja ungern "schwieriger") in der Codierung



  • In einer J2EE Umgebung wird der Code so ca. 600 mal interpretiert ausgeführt. Währenddessen sammelt der JIT ( wieso eingentlich JIT?) Profiler Informationen. In einem separaten Task wird dann der Code hoch optimiert übersetzt. (Interessanterweise wird Byte Code so gut wie gar nicht optimiert)

    Dieses Profiling kannst du aber auch in C++ haben, das ist kein Alleinstellungsmerkmal eines JIT. Es gibt von den bekannten C++-Compilern mittlerweile auch PGO (Profile-Guided Optimization):
    http://msdn.microsoft.com/de-de/library/e7k32f4k.aspx
    Und seien wir ehrlich, die meisten Programme laufen gleich ab. Die meisten User benutzen eine Software gleich.

    C/C++ hat grundsätzlich die Nachteile:
    - Es baut und optimiert den Objectcode pro Datei, nicht pro Library. Da geht einem durch ungeschicktes Programmieren schon mal Faktor 10 ( in Worten: zehn ) verloren. Das ist eigentlich nur ein C++ Problem.

    Ehm, naja, das stimmt aber auch nicht mehr. Beim kompilieren und debuggen mag zwar alles auf Objektcode-Dateien stur kompiliert sein, aber was ist (wie bei PGO) mit dem Release-Build? genau, da haben die C++-Compiler heute natürlich auch eine Lösung: WPO (Whole Program Optimization)
    http://msdn.microsoft.com/de-de/library/0zza0de8.aspx

    Einige vergessen immer wieder eines: Auch C++ und vorallem seine Tools entwickeln sich weiter. Es lohnt sich auch mal über die aktuellen Compiler zu informieren.



  • Wie macht man eine wirklich tolle PGO, wenn man das Zielsystem nicht genau kennt? Ein JIT könnte auf den genauen Prozessor, dessen Cache-Größe und sogar auf das aktuell zur Verfügung stehende RAM hin optimieren. Vermutlich kriegt man das aber auch mit C++ hin, einfach 30-40 verschiedene Executables für unterschiedlichste Situationen liefern. 😉



  • Jester schrieb:

    Wie macht man eine wirklich tolle PGO, wenn man das Zielsystem nicht genau kennt? Ein JIT könnte auf den genauen Prozessor, dessen Cache-Größe und sogar auf das aktuell zur Verfügung stehende RAM hin optimieren. Vermutlich kriegt man das aber auch mit C++ hin, einfach 30-40 verschiedene Executables für unterschiedlichste Situationen liefern. 😉

    indem man genau wie bei java nicht das finale binary, sondern den compiler input mitliefert. Ist bei den meisten dingen unter bsd/*nux eh der fall.



  • Zui schrieb:

    ...
    Java hat grundsätzlich die Nachteile:
    ...
    C/C++ hat grundsätzlich die Nachteile:
    ...

    Hmmm also ich sehe weder hier noch dort Nachteile, die in der Sprache begründet seien, sondern lediglich Vergleiche spezieller Vorgehensweisen/Konfiguratioen/Tooleigenschaften im Entwicklungs- und im Laufzeitumfeld.

    Ich wüsste nicht, warum die o.g. "C++-Vorteile" nicht genauso mit Java-Programmen und anders herum genutzt werden könnten.

    Gruß,

    Simon2.



  • rapso schrieb:

    Jester schrieb:

    Wie macht man eine wirklich tolle PGO, wenn man das Zielsystem nicht genau kennt? Ein JIT könnte auf den genauen Prozessor, dessen Cache-Größe und sogar auf das aktuell zur Verfügung stehende RAM hin optimieren. Vermutlich kriegt man das aber auch mit C++ hin, einfach 30-40 verschiedene Executables für unterschiedlichste Situationen liefern. 😉

    indem man genau wie bei java nicht das finale binary, sondern den compiler input mitliefert. Ist bei den meisten dingen unter bsd/*nux eh der fall.

    Wie lange dauert es, bis Dein aktuelles Projekt durch den Compiler gelaufen ist? Wie praktikabel wäre das?



  • Jester schrieb:

    rapso schrieb:

    Jester schrieb:

    Wie macht man eine wirklich tolle PGO, wenn man das Zielsystem nicht genau kennt? Ein JIT könnte auf den genauen Prozessor, dessen Cache-Größe und sogar auf das aktuell zur Verfügung stehende RAM hin optimieren. Vermutlich kriegt man das aber auch mit C++ hin, einfach 30-40 verschiedene Executables für unterschiedlichste Situationen liefern. 😉

    indem man genau wie bei java nicht das finale binary, sondern den compiler input mitliefert. Ist bei den meisten dingen unter bsd/*nux eh der fall.

    Wie lange dauert es, bis Dein aktuelles Projekt durch den Compiler gelaufen ist? Wie praktikabel wäre das?

    Das Kompilieren des Programms gehört zur Installation. Das kann man wohl kaum zur Laufzeit dazurechen. ⚠
    Außerdem kompiliert man das Programm nur EINMAL. Java Programme werden hingegen bei JEDEM Start neu JIT kompiliert. ⚠



  • ⚠ mit cobol wär das nich passiert ⚠



  • Jester schrieb:

    Wie macht man eine wirklich tolle PGO, wenn man das Zielsystem nicht genau kennt? Ein JIT könnte auf den genauen Prozessor, dessen Cache-Größe und sogar auf das aktuell zur Verfügung stehende RAM hin optimieren. Vermutlich kriegt man das aber auch mit C++ hin, einfach 30-40 verschiedene Executables für unterschiedlichste Situationen liefern. 😉

    Na, 30-40 Exes ist ja mal übertrieben. Seien wir ehrlich: eine solche filigrane Optimierung macht nur bei wenigen Spezialanwendungen Sinn. Oder meint ihr, das sich PGO bei OpenOffice lohnen würde (ich meine spürbar!)? Nein, sicherlich nicht. Solche Anwendungen kompiliert man heute mit den normalen Optimierungs-Flags. Ein 3D-Spiel z.B. kann man für nen Pentium 4 kompilieren lassen (wenns eh als Mind-Anforderung auf der Packung steht).

    So, wann liefere ich aber als Software-Anbieter eine super optimierter Variante aus? Dann wenn ich eine Anwedung habe, wo sich z.B. PGO bemerkbar macht. Und das sind erstens nur die wenigsten Anwendungen und zweitens lässt man sich solche Anwendungen eh mit nem Extra-Preis bezahlen. Nehmen wir mal so eine Oracle-DB-Server: der kostet nicht 50 EUR, sondern bei einer Konzernlizenz mit Full-Support mehrere tausend Euro. Wir haben bei uns teilweise Software im Konzern, die für 250.000 EUR eingekauft wurde. Ehm... ja, da kann der Software-Anbieter natürlich locker eine speziell für die Ziel-Hardware optimierte Executable und Libs ausliefern. Warum auch nicht? Denn die Hardware beim Kunden wechselt ja nicht alle 2 Monate. Bei uns laufen Server und Mainframes Jahre durch.

    Das bei Java der JIT immer wieder neu optimiert, wenn die JAR angestartet wird, ist Design-bedingt, aber kein Vorteil ggü. C++.

    Und es gibt ja auch schon heute Closed-Source-Software, wo der Anbieter eh mehrere EXEs für verschiedene Plattformen anbietet... siehe Codeforge-IDE. Die haben mind. 6 verschiedene Binaries im Angebot, je nach dem was der Kunde für eine Plattform hat.

    Bei Opensource ist dann eh alles anders, da kann der Kunde selber seine PGO einstellen, wenn es dafür keinen Anbieter gibt. Aber auch solche Aufgaben können Opensource-Dienstleister übernehmen, will man es nicht selbst machen.

    Und wie gesagt, PGO macht meiner Meinung bei Meinstream-Anwendungen keinen wirklich große Sinn. Und ist bei C++ in dem Bereich auch nicht nötig.



  • Die meisten meinen hier irgendwie, dass Java-Serverprogramme einfach mit C++ Desktopprogrammen verglichen werden können und versuchen dann Konzepte 1:1 von der einen Welt in die andere zu übertragen.



  • Jester schrieb:

    rapso schrieb:

    Jester schrieb:

    Wie macht man eine wirklich tolle PGO, wenn man das Zielsystem nicht genau kennt? Ein JIT könnte auf den genauen Prozessor, dessen Cache-Größe und sogar auf das aktuell zur Verfügung stehende RAM hin optimieren. Vermutlich kriegt man das aber auch mit C++ hin, einfach 30-40 verschiedene Executables für unterschiedlichste Situationen liefern. 😉

    indem man genau wie bei java nicht das finale binary, sondern den compiler input mitliefert. Ist bei den meisten dingen unter bsd/*nux eh der fall.

    Wie lange dauert es, bis Dein aktuelles Projekt durch den Compiler gelaufen ist? Wie praktikabel wäre das?

    wie praktikabel linux/bsd/etc. mit den source packeten ist? naja, afaik ist das der source weg die beliebteste verbreitungsmethode von software auf diesen systemen. sogar das ganze OS kann man sich als source ziehen, obwohl viele distributionen precompilierte binaries haben, aber wenn du dir z.b. gentoo ziehst, oder auf ps2 das linux installierst, bekommst du alles fuer dein system perfect zugeschnitten compiliert.
    Da die dinge als source vorliegen und nicht nur als bytecode, kannst du auch weit mehr optimieren.



  • Der Grund warum alle neueren Sprachen* einen JIT einsetzen liegt meines erachten darin, dass man eh eine Art Bytecode-Zwischen-Code braucht um alle heute üblichen Optimierungen zu unterstützen und man dadurch den JIT sozusagen ohne großen Aufwand dazu kriegt.

    Das reine C/C++-Übersetzungsmodel erlaubt nun einmal keine intermodularen Optimierungen. Inlinen besteht nicht nur daraus den Funktionskörper zu Copy & Pasten sondern auch aus dem Auswerten dadurch entstehender konstanter Ausdrücke und vor allem aus einer effektiven Registerverteilung in der entstehenden Funktions. Mit fertigem x86 Maschinen Code sind diese Optimierungen quasi unmöglich und arten meisten in einem Minidecompiler aus welcher in den Linker integriert wird.

    Wenn man nun allerdings den Code zuerst in Bytecode verwandelt dann sind solche intermodularen Optimierungen eigentlich kein Thema mehr. Der Compiler inlined gar nichts mehr und der "Linker" kümmert sich um sämtliche Optimierungen dieses Typs. Wenn der Bytecode weise gewählt wurde dann geht das sogar sehr flott.

    Ob man Bytecode produziert ist also nicht mehr die Frage. Es geht einzig darum ob man ihn in Maschinencode fertig kompiliert oder eine VM einsetzt. Hier entscheidet man sich dann meisten für die VM da diese doch ein paar nette Vorteile bietet wie zum Beispiel die Prozessorunabhängigkeit der Programme.

    Um ein C/C++ Programm auf dem Zielrechner erst während der Installation zu übersetzen braucht man alle verwendeten Headers in der richtigen Version (und alle dazugehörigen Source Dateien wenn man intermodulare Optimierungen erst nimmt). Auf nicht Programmierer-Rechnern ist das eine ziemlich starke Abhängigkeit. Bei *nix ist das dank Packetverwaltung noch im Bereich des machbaren. Bei Windows sehe ich aber schwarz.

    *Implementierungen für Korinthen-Hacker



  • COBOL-Fan schrieb:

    Das Kompilieren des Programms gehört zur Installation.

    was? also ne. das fehlte noch.
    🙂



  • rapso schrieb:

    wie praktikabel linux/bsd/etc. mit den source packeten ist?

    du hast wieder mal nix gelesen und haust nur blinde drauf, gell? Kannst Du bitte bitte mal aufhören davon auszugehen, dass ich irgendwie völlig beschränkt bin? Oder kompilierst Du tatsächlich die Anwendung vor jeder Benutzung, um sie auch auf die aktuelle Systemauslastung hin zu optimieren (z.B. größe vs. geschwindigkeit). wie ist das bei dir bei der arbeit, legt ihr auch die sourcen bei? wie praktikabel ist das?



  • Ich bin immer wieder überrascht, warum anscheinend implizit davon ausgegangen wird, dass C++ und JIT-Compilierung sich gegenseitig ausschließen.

    Ich sehe selber große Vorteile bei der JIT-Compilierung, was das linken von dynamischen Libraries angeht, das ermöglicht inlining und erleichtert imho auch den Export von Klassen. Mir gefällt die momentane Lösung vom VC++ nicht, man kann zum Beispiel keine Klasse exportieren, die Member hat, deren Typ nicht exportiert ist, auch wenn dieser Member gar nicht Teil der öffentlichen Schnittstelle ist. Dieses ganze Speicherlayout-Gefrickel kann mit JIT-compilierung wahrscheinlich wesentlich eleganter gelöst werden.

    Aber irgendwie wird immer C++ und JIT-Compilierung gegenüber gestellt, das finde ich leicht irritierend. 😕



  • Jester schrieb:

    rapso schrieb:

    wie praktikabel linux/bsd/etc. mit den source packeten ist?

    du hast wieder mal nix gelesen und haust nur blinde drauf, gell? Kannst Du bitte bitte mal aufhören davon auszugehen, dass ich irgendwie völlig beschränkt bin? Oder kompilierst Du tatsächlich die Anwendung vor jeder Benutzung, um sie auch auf die aktuelle Systemauslastung hin zu optimieren (z.B. größe vs. geschwindigkeit). wie ist das bei dir bei der arbeit, legt ihr auch die sourcen bei? wie praktikabel ist das?

    Diese Optimierungsmöglichkeiten halte ich für übertrieben theoretisch.



  • Optimizer schrieb:

    Jester schrieb:

    rapso schrieb:

    wie praktikabel linux/bsd/etc. mit den source packeten ist?

    du hast wieder mal nix gelesen und haust nur blinde drauf, gell? Kannst Du bitte bitte mal aufhören davon auszugehen, dass ich irgendwie völlig beschränkt bin? Oder kompilierst Du tatsächlich die Anwendung vor jeder Benutzung, um sie auch auf die aktuelle Systemauslastung hin zu optimieren (z.B. größe vs. geschwindigkeit). wie ist das bei dir bei der arbeit, legt ihr auch die sourcen bei? wie praktikabel ist das?

    Diese Optimierungsmöglichkeiten halte ich für übertrieben theoretisch.

    mag sein, aber das war ja nicht rapsos Argument.

    ah, hast du grad mal nen link zu so einem C++ JIT Compiler?



  • Jester schrieb:

    rapso schrieb:

    wie praktikabel linux/bsd/etc. mit den source packeten ist?

    du hast wieder mal nix gelesen und haust nur blinde drauf, gell?

    doch ich hab's gelesen (jedenfalls 4seiten zurueck) und hab gesagt dass sowas in der art gemacht wird. genau wie es JIT gibt die sowas machen beim ersten start, also vor dem start, dem system entsprechend neu bauen. manche JIT lassen einen profilelauf rennen und beim zweiten start wird dann die system angepasste version gebaut.

    Kannst Du bitte bitte mal aufhören davon auszugehen, dass ich irgendwie völlig beschränkt bin?

    sehr gerne.

    Oder kompilierst Du tatsächlich die Anwendung vor jeder Benutzung, um sie auch auf die aktuelle Systemauslastung hin zu optimieren (z.B. größe vs. geschwindigkeit).

    nein, das waere voellig "beschraenkt". die laufleistung haengt bei den allermeisten programmen von den daten ab, nicht so sehr von compilierflags. wenn ich photoshop neu compilieren wuerde, weil ich mir ein icon ansehen will, aber weil mein system gerade speichermaessig ausgelastet ist, ich alles neu bauen muss um es mir dann in 1.5 statt 1.6mb anzusehen, waere das recht sinnfrei.

    deswegen, erst profilen, dann optimieren, ergo: pgo. entsprechend gehoeren daten zum profilen und optimieren dazu.

    wie ist das bei dir bei der arbeit, legt ihr auch die sourcen bei? wie praktikabel ist das?

    wir haben builds fuer die gelaeufigsten systeme. diese bauen ueber nacht durch. alles in allem sind es ca 10 8-core server + ca 100 distributed clients die ca 3stunden bauen, wobei das production builds sind, die sind entsprechend nicht bis zum ende optimiert, da es noch keine finalen daten gibt.

    mit finalen daten benutzen wir halt pgo, und das fuer verschiedene systeme und verschiedene teile eines builds. du wuerdest es nicht glauben wieviele permutationen wir haben.

    aber wenn du es wissen willst, wie praktikabel es ist das optimale programm zu bauen, versuch gerne mal: http://www.coyotegulch.com/products/acovea/

    ich glaube dann kommt jeder zu dem schluss...



  • Was macht ihr mit den vielen Permutationen dann? Werden die tatsächlich alle ausgeliefert und für den Kunden die jeweils passendste gewählt, oder nehmt ihr die, die im Durchschnitt über die Systeme die beste Performance liefert?


Anmelden zum Antworten