JAVA schneller als C++ ? Stimmt das???



  • Für jede Programmiersprache wirst Du Fälle finden, die in der jeweiligen Sprache schneller sind als in anderen.
    So ist z.B. C# beim allokieren viel schneller...

    Aber hat das irgendwas mit "real-world" Applikationen zu tun?
    In 99,999999% der Fälle nicht.



  • So ist z.B. C# beim allokieren viel schneller...

    In C++ kann man es aber genauso schnell nachbilden.



  • Jochen Kalmbach schrieb:

    So ist z.B. C# beim allokieren viel schneller...

    viel schneller als was?

    topic: natürlich ist java nicht schneller. ausserdem heiist es *als* nicht 'wie'



  • heisst es nicht "als wie" 🙂

    Ausserdem: Solange es keine 3d-Shooter, Video Codecs oder sonstiges Performance-Kritisches Zeug gibt das in Java geschrieben ist, würde ich diesen Schwachfug nicht glauben...



  • basic ist schneller wie turbo pascal. nur mal so als beispiel.



  • pfffffff schrieb:

    So ist z.B. C# beim allokieren viel schneller...

    In C++ kann man es aber genauso schnell nachbilden.

    Nein. Aber das ist eine andere Geschichte...

    @net: als C++



  • Jochen Kalmbach schrieb:

    @net: als C++

    als c++ ??
    man kann doch 'n memory allocator leicht austauschen in c++. da kann man doch nicht pauschal behaupten dass .NET immer schneller ist als c++. hast du irgendwelche links wo das steht?



  • frenki schrieb:

    heisst es nicht "als wie" 🙂

    nur bei Goethe. der derf das 😉



  • Der Grund ist ganz simpel: C# hat einen GC und brauch beim allokieren einfach einen Index erhöhen; schon ist der Speicher allokiert (also fast i++).
    C++ hat keinen GC und muss somit beim allokieren zuerst mal eine Liste mit Speicherblöcken durchwandern, bis einer gefunden wurde, welcher eine passende Größe hat.
    Also ganz grob:

    class Foo
    {
      int B;
      int a;
      int r;
    };
    
    test()
    {
      Foo arrayOfFoo[10000000];
      for(int i=0; i<10000000; i++)
      {
        arrayOfFoo[i] = new Foo();
      }
    }
    

    ist in C# um Faktoren schneller als in C++

    PS: Aber was hat so ein Test mit einer "Real-World-App" zu tun????



  • Jochen Kalmbach schrieb:

    Der Grund ist ganz simpel: C# hat einen GC und brauch beim allokieren einfach einen Index erhöhen; schon ist der Speicher allokiert (also fast i++).

    heisst das, dass die zeile:

    Foo arrayOfFoo[10000000];
    

    schonmal alle objekte alloziert und das 'new' nur noch einen index hochzählt und konstruktoren aufruft?
    oder wie soll man das verstehen?



  • net schrieb:

    heisst das, dass die zeile:

    Foo arrayOfFoo[10000000];
    

    schonmal alle objekte alloziert und das 'new' nur noch einen index hochzählt und konstruktoren aufruft?

    Nein. Hier wird nix alloziert (nur der Pointer-Speicher für die Klasse; nicht aber die Klasse selber).

    Um das im Tiefen zu verstehen, muss Du wissen wie ein GC funktioniert.
    Hier wird es erklärt:
    http://msdn.microsoft.com/msdnmag/issues/1100/gci/
    http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/

    Der Hauptunterschied (der für den Test relevant ist) ist, dass ein allokieren in dem GC-Heap nur ein verschieben eines Zeigers um die Größer des zu allokierenden Objektes darstellt (also NextObjPtr = NextObjPtr + SizeOfObject).
    Das ist nun mal eine sehr simple Operation. In C++ wird dagegen eine verkettete Liste nach passenden Einträgen durchsucht.

    Ein kurzer Test ergab:
    C++: 3672 ms
    C#: 2203 ms

    Hier der Code:

    #include <windows.h>
    #include <tchar.h>
    #include <vector>
    
    class Foo
    {
      int B;
      int a;
      int r;
    };
    int _tmain()
    {
      Foo **arr = new Foo*[10000000];
      DWORD dwStart = GetTickCount();
      for(int i=0; i<10000000; i++)
      {
        arr[i] = new Foo();
      }
      DWORD dwEnd = GetTickCount();
      _tprintf(_T("%d ms"), dwEnd - dwStart);
    }
    

    C#:

    using System;
    namespace ConsoleApplication
    {
      class Foo
      {
        int B;
        int a;
        int r;
        static void Main(string[] args)
        {
          Foo [] al = new Foo[10000000];
          DateTime start = DateTime.Now;
          for(int i=0; i<10000000; i++)
          {
            al[i] = new Foo();
          }
          DateTime stop = DateTime.Now;
          TimeSpan ts = stop-start;
          Console.WriteLine("{0} ms", ts.TotalMilliseconds);
        }
      }
    }
    

    PS: Ich hatte mal ein Beispiel, wo der Unterschied noch größer war... müsste ich jetzt aber zuerst mal suchen...
    PPS: Ok, im Release sind es nur noch C++: 2016 ms und C#: 1687 ms (immerhin ist C++ noch ca. 20% langsamer als C#)



  • okay, danke für die links.
    demnach ist es mit .NET tatsächlich schneller objekte zu erzeugen als mit einem 'linked-list' heap. allerdings, wenn der garbage collector zuschlägt geht wieder etwas zeit verloren, die .NET im vergleich zu einem c++ -new gewonnen hat. aber über einen grösseren zeitraum, schätze ich, wird die .NET methodik etwas schneller sein... aber zum glück kann man ja 'new' in c++ austauschen und einen ähnlich schnellen memory allocator nehmen 🙂



  • Hi,

    also ich hab mal den C++ Code in Managed C++ (CLI) umgeschrieben, sodass man beide Programme am Framework vergleichen kann:

    C++: 2093 ms
    C#: 2171 ms

    using namespace System;
    
    ref class Foo
    {
        int B;
        int a;
        int r;
    };
    
    int main()
    {
        array<Foo^ > ^al = gcnew array<Foo^ >(10000000);
        DateTime start = DateTime::Now;
        for (int i = 0; i < 10000000; i++)
        {
            al[i] = gcnew Foo();
        }
        DateTime stop = DateTime::Now;
        TimeSpan ts = stop - start;
        Console::WriteLine("{0} ms", ts.TotalMilliseconds);
        Console::ReadLine();
    
        return 0;
    }
    

    Könnte daran liegen, dass der C++ Compiler/Linker besser Optimiert ist (da es den ja länger gibt 😉 )



  • vielleicht macht mal einer den test mit java? das müsste ja eigentlich ähnlich schnelle heapalgorithmen haben, weil man da auch immer mit vielen objekten hantieren muss....



  • cppgast schrieb:

    In der c't war schon vor 3 oder 4 Jahren zu lesen, dass C++ von Java im Bereich der Konsolenprogramme locker an die Wand gedrückt wird.

    Solchen Sachen solltest du nicht allzu viel Glauben schenken. "Java schneller als C++?" Darauf gibt es keine Antwort. C++ ist eine reine Sprachdefinition, und davon kannst du keine Geschwindigkeit messen. Genauso wenig wie vom BGB. Was du messen kannst, sind Implementationen. Diese zu beurteilen, kann man aber nur subjektiv und nicht objektiv. Ich kann dir 100 Implementierungen zu einem Problem in C++ liefern (glücklicherweise muss ich das nicht 🙂 ), und jede hat ein anderes Laufzeitverhalten.
    Wenn man überhaupt eine objektive Antwort auf die Frage geben kann, dann kannst du das auch ohne irgendwelche Benchmarks, nur rein von der technischen Seite betrachtet. C++ Programme werden idR direkt für die jeweilige Plattform kompiliert, laufen also nativ. Java wird hingegen interpretiert, auch wenn das heutzutage bei weitem nicht mehr so spartanisch abläuft wie zu Basic Zeiten. AFAIK ist es zwar auch möglich, nativen Code zu erzeugen. Das dürfte aber nicht die Regel sein. Wie auch immer, der von der VM verarbeitete übliche Bytecode ist gegenüber nativem Code ein weiterer Zwischenschritt der einfach Laufzeit kostet, weil keine VM der Welt Instruktionen so effizient verarbeiten kann wie ein Prozessor. Die VM kann ja maximal auch nur das machen, was der Prozessor hergibt. Von daher sind C++ Anwendungen auf dem Papier erstmal performanter einzustufen als Java Anwendungen. Wie aber letztendlich die Realität, und damit die konkrete Implementierung aussieht, ist eine ganz andere Geschichte.
    Das eigentlich Traurige daran ist, dass man im Netz immer wieder "Dünnbrettbohrer" findet, die von der Materie nicht wirklich Ahnung haben und dann mit Benchmarks _ihre_ Sprache anpreisen.
    Auf einer Webseite (Adresse weiss ich leider nicht mehr) habe ich mir mal so einen Benchmark Test zwischen C++ und Java Programmen näher angeschaut. Das war der helle Wahnsinn, was für einen Blödsinn dieser Typ dort gemacht hat. Ich sollte vllt. noch dazu sagen, dass es ein Java Verfechter war und die Ergebnisse auch entsprechend aussahen. Aber das nur nebenbei. Jedenfalls hat er diverse Algorithmen implementiert und die Anwendungen dann mittels eines Skripts mehrfach hintereinander aufgerufen und die Zeit gemessen. Was der Typ aber nicht bedacht hatte, ist, dass die Anwendungen auch beim Start und Beenden Laufzeit verbraten. Die eigenliche Laufzeit des Algorithmus ist somit nur zu einem gewissen Teil im Ergebnis enthalten. Und dieses ist somit vollkommen unbrauchbar. Soviel zum Thema stupide Ignoranten. 😉



  • "JAVA schneller wie C++ ? Stimmt das??? "

    Schwachsinn Wer so etwas diskutiert, hat noch nie programmiert.



  • Dauercoder schrieb:

    Hi,

    also ich hab mal den C++ Code in Managed C++ (CLI) umgeschrieben, sodass man beide Programme am Framework vergleichen kann:

    C++: 2093 ms
    C#: 2171 ms

    [snip]

    Könnte daran liegen, dass der C++ Compiler/Linker besser Optimiert ist (da es den ja länger gibt 😉 )

    Hi,

    jepp, daran wirds liegen...
    Du gewinnst durch den Benchmark allerdings nichts, da der Algorithmus des .net Frameworks ja der gleiche ist, egal, ob du C# oder C++/CLI verwendest. Aussagen wie "der Allokationsalgorithmus in C++ ist schneller als der in C#" kann man damit also nicht beweisen. (Mal abgesehen davon, dass das ohnehin Schwachsinn ist, da man immer nur den Algorithmus einer C++-Implementation testen kann.)

    Mich würde mal interessieren, was hier ein angepasster Allokator bringen würde 🙂



  • Mit der Sprache hat das nichts zu tun. Eher wird der Allokator der Sprache angepasst, denn man braucht einen den Umständen entsprechend passenden Allokator. In C ist malloc meistens auf das allokieren von wenigen großen Blöcken unterschiedlicher Länge optimiert. In C++ macht man viel mehr mit new rum, deshalb ist die Speicherverwaltung dort auch auf das allokieren vieler kleinerer Blöcke besser optimiert. Am meisten allokiert man in Sprachen wie Java und C#, meistens leben die Objekte auch nur sehr kurz und das ist genau das, was der GC sehr gut behandeln kann.

    Möglicherweise wäre das auch für ein typisches C++ Programm die optimalere Lösung als die derzeitigen Implementierungen, aber es ist nicht trivial, einen guten GC zu schreiben und trotzdem Pointer wie in C++ zu erlauben. In C++/CLI geht es auch nur mit dem ^-Zeiger so gut. Das Allokieren mit dem normalen new ist auch dort eher schlechter als gcnew, weil die meisten Programme, wie man sie heute schreibt, einen GC begünstigen.



  • groovemaster schrieb:

    Wenn man überhaupt eine objektive Antwort auf die Frage geben kann, dann kannst du das auch ohne irgendwelche Benchmarks, nur rein von der technischen Seite betrachtet. C++ Programme werden idR direkt für die jeweilige Plattform kompiliert, laufen also nativ. Java wird hingegen interpretiert, auch wenn das heutzutage bei weitem nicht mehr so spartanisch abläuft wie zu Basic Zeiten. AFAIK ist es zwar auch möglich, nativen Code zu erzeugen. Das dürfte aber nicht die Regel sein. Wie auch immer, der von der VM verarbeitete übliche Bytecode ist gegenüber nativem Code ein weiterer Zwischenschritt der einfach Laufzeit kostet, weil keine VM der Welt Instruktionen so effizient verarbeiten kann wie ein Prozessor. Die VM kann ja maximal auch nur das machen, was der Prozessor hergibt. Von daher sind C++ Anwendungen auf dem Papier erstmal performanter einzustufen als Java Anwendungen.

    Blah blah blah! Hattest Du in deinem Beitrag nicht auch was von "Ahnung haben" und so geschrieben?

    Was Du da sagst ist zum eine Verzerrung der Tatsachen und zum anderen heutzutage kein wirklicher Performanceaspekt mehr, wenn es darum geht, ob Java nun schnell oder lahm ist.

    1. Es ist deshalb eine Verzerrung der Tatsachen, weil die JVM den Bytecode zur Laufzeit kompiliert. Das geht auch relativ schnell, weil der Bytecode schon relativ nah an einem passenden Maschinencode dran ist. Es macht deshalb nichts aus, weil die dafür benötigte Zeitdauer mehr als so eine Art konstanter Overhead gesehen werden kann. Diese Zeitdauer hängt nicht davon ab, wie komplex die Daten sind, die Du in einen Algorithmus reinschaufelst. Und da Du Performance meistens da brauchst, wo Du viel verarbeiten musst, kann dieser Aspekt eigentlich vernachlässigt werden. Zudem können - wenn Du so prinzipielle Erwägungen machst - bei einer Kompilation zur Laufzeit bessere Optimierungen vorgenommen werden. Hier ist zum einen die genaue darunterliegende Plattform bekannt, zum anderen ist aber auch der Zustand des Programms bekannt. Beide Aspekte könnten - vom Prinzip her - zu besser optimiertem Maschinencode führen. Aber wie Du schon sagst: Die Realität entspricht nicht unbedingt den prinzipiellen Möglichkeiten.

    2. Für die Performance von Javaprogrammen sind bestimmte Eigenarten im Sprachdesign von Java deutlich problematischer als der von Dir erwähnte Punkt. Bestimmte Eigenschaften von Java machen einen gut optimierten Code umständlicher zu programmieren, als das vielleicht in C++ der Fall wäre. Ein Beispiel hierfür sind die primitiven Datentypen: Hierfür sind in der Standardbibliothek zum Beispiel keine Containerklassen vorhanden. Java bietet Generizität nur für Objekte. Wenn man also mit den primitiven Datentypen performanten Code bekommen will, muss man sich für diese Extraimplementationen von den benutzten Datenstrukturen und Algorithmen besorgen. Zum Beispiel, indem man eine externe Bibliothek verwendet oder indem man entsprechend redundant jeden Algorithmus mehrmals schreibt. Das ist Umständlich und deshalb überlegt man sich natürlich genau, ob man das an einer gegebenen Stelle wirklich braucht. Und genauso gibt es noch einige weitere Eigenschaften von Java, die performanten Code einfach "umständlich zu programmieren" machen. Die meisten Performanceprobleme, die man mit Javaprogrammen hat, sind eher auf solche Schwierigkeiten zurückzuführen, als auf die typischerweise erwähnten Dinge wie "Interpretierter Code", "GC", "Indexüberprüfungen" usw..

    3. Natürlich werden C++ Programme bei den heute üblichen Compilern im Großen und Ganzen etwas schneller laufen als entsprechende Javaprogramme. Java muss nicht die schnellsten Programme liefern. Ich denke, Java hat, trotz seinem Langsam-Image, eine ziemliche Bedeutung bekommen. Insofern scheint Geschwindigkeit in vielen Anwendungsgebieten nicht gerade der wichtigste Punkt zu sein. Java bietet offensichtlich auch andere Dinge. Und unter diesem Gesichtspunkt sollte man die Performance von Javaprogrammen sehen. Heutzutage kommt man damit oft schon sehr in die Nähe von entsprechenden C++ Programmen, weil sich in der JVM in den letzten 10 Jahren eine Menge getan hat. Am Anfang waren Javaprogramme vielleicht um einen Faktor 100 langsamer als entsprechende C++ Programme. Heutzutage ist es in günstigen Fällen vielleicht nur noch ein Faktor 1,5 (und in Trivialfällen existiert teilweise fast gar kein Unterschied mehr). Wenn es um die Performance von Javaprogrammen geht, ist letztendlich die Frage, ob das ein entscheidender Nachteil in einem bestimmten Anwendungsgebiet ist. Das trifft heutzutage nur noch auf wenige Anwendungsgebiete zu. Trotz allem ist die Frage aus meiner Sicht nicht, ob Java da im Vorteil wäre. Wer soetwas für den allgemeinen Fall behauptet, nimmt die Realität wahrscheinlich etwas verzerrt wahr. Wer für einen bestimmten Anwendungsfall die optimale Performance braucht, wird auch in absehbarer Zukunft in erster Linie auf C++ setzen. Die Frage ist aber immer, ob man diese optimale Performance wirklich braucht.



  • Die Praxis zeigt sich aber das so ziemlich jedes Java-Programm zu langsam ist.


Anmelden zum Antworten