Warum läuft Java hier schneller als C?

8

Inspiriert von diese Frage ,

Jetzt nur für Benutzer mit & gt; 10k Wiederholung

Ich habe den folgenden Code gefunden:

%Vor%

Warum läuft die Java-Version fast 3x schneller als die C-Version? Was ich hier vermisse?

Dies wird unter Ubuntu 9.04 mit:

ausgeführt

Intel® Pentium (R) M @ 1.73GHz

32 Bits

BEARBEITEN

Das ist erstaunlich. Mit der -O3-Option in C optimieren Sie die Schleife und die Verwendung von -server in Java tut das gleiche. Dies sind die "optimierten Zeiten". optimiert http://img196.imageshack.us/img196/6489/screenshot4rv.png

    
OscarRyz 14.02.2010, 04:41
quelle

9 Antworten

30

Ich erwarte, dass javac auf eine höhere Optimierungsebene als Ihr C-Compiler voreingestellt ist. Wenn ich hier mit -O3 kompiliere, ist das C viel schneller:

C mit -O3 :

%Vor%

Dein Java-Programm:

%Vor%

Einige weitere Details; Ohne Optimierung kompiliert das C zu:

%Vor%

Bei optimierung ( -O3 ) sieht das so aus:

%Vor%

Wie Sie sehen können, wurde die gesamte Schleife entfernt. javap -c Loop gab mir diese Ausgabe für den Java-Bytecode:

%Vor%

Es scheint, dass die Schleife kompiliert ist, ich denke, dass etwas zur Laufzeit passiert, um das zu beschleunigen. (Wie andere bereits erwähnt haben, quetscht der JIT-Compiler die Schleife aus.)

    
Carl Norum 14.02.2010, 04:45
quelle
9

Meine Vermutung ist, dass der JIT die leere Schleife optimiert.

Update: Der Java Performance Tuning-Artikel Follow up to Empty Loop Benchmark scheint dies zusammen mit dem anderen zu unterstützen Antworten hier, die darauf hinweisen, dass der C-Code auch optimiert werden muss, um einen sinnvollen Vergleich zu ermöglichen. Schlüsselzitat:

  

Hätte ich gewählt, den Client-Modus 1.4.1 JVM zu verwenden (Client ist der Standardmodus), würden die Schleifen nicht weg optimiert werden. Hätte ich mich für den C ++ - Compiler von Microsoft entschieden, würde die C-Version keine Zeit benötigen. Offensichtlich ist die Wahl des Compilers kritisch.

    
Bill the Lizard 14.02.2010 04:44
quelle
5

Es gibt einige Dinge, die Sie hier kontrollieren müssen:

  • der Start der JVM ist im Vergleich zum Start eines kompilierten C-Programms
  • nicht-trivial
  • Ihre Schleife tut nichts und der Compiler weiß das wahrscheinlich
  • JIT-Compiler produzieren oft besseren Code als ein nicht optimierter C-Compiler
Greg Hewgill 14.02.2010 04:43
quelle
5

"Was ich hier vermisse?" Optimierungsflags

    
ergosys 14.02.2010 04:43
quelle
5

Ich denke nicht, dass diese Frage wirklich eine Antwort hat; Es hängt von den Optimierungen ab, die beide Compiler durchführen. In diesem Fall erwarte ich entweder, wenn in einen ausreichenden Optimierungsaufwand gestoßen würde, würde die Schleife vollständig eliminieren, da i niemals verwendet wird.

    
Jeff Walden 14.02.2010 04:44
quelle
4

Optimierung - Sie fehlen zumindest das -O2 -Flag in der Befehlszeile gcc .

    
Nikolai Fetissov 14.02.2010 04:45
quelle
2

Der Java-JIT-Compiler ist schlau genug, um die Schleife zu optimieren, während der C-Compiler anscheinend die meisten Optimierungen ausgeschaltet hat.

Sie vergleichen also wirklich die Zeit, um die Java-Maschine zu starten, mit der Zeit, die unoptimierter C-Code benötigt, um auf 2 Milliarden zu zählen.

    
John Knoeller 14.02.2010 04:59
quelle
2

Da das Programm nichts macht, kann ein Optimierer die Schleife entfernen

Wenn Sie versuchen, einen Compiler dazu zu bringen, eine bestimmte Einheit oder, na ja, Benchmark der Arbeit zu machen, dann müssen Sie es täuschen, dass das Ergebnis der Arbeit tatsächlich verwendet wird.

Eine Möglichkeit besteht darin, eine Funktion in eine Datei zu schreiben, zu kompilieren und dann mit dem Setup aus einer anderen Datei aufzurufen. Kein Compiler kann vorhersehen, was in Zukunft kompiliert wird.

Ohne das ist es nur eine Art Wettbewerb zwischen Standard-Optimierungsstufen und hat keine nützliche Bedeutung.

    
DigitalRoss 15.02.2010 06:52
quelle
0

Ihr Programm tut absolut nichts, das sagt nichts über die Leistung beider Sprachen aus. Das einzige, was es Ihnen sagt, ist, wenn Ihr Compiler das herausfinden kann und deshalb Ihr Programm komplett überspringt.

Um es "etwas" zu tun, müssten Sie jedes Inkrement auf stdout drucken. Wenn Sie nur das Endergebnis drucken, könnte ein guter Compiler Ihr Programm auf eine Anweisung optimieren, die nur dieses Ergebnis ausgibt und die gesamte "Berechnung" überspringt.

    
ahe 14.02.2010 10:41
quelle

Tags und Links