Java vs. C. Performance-Vergleich
-
maximAL schrieb:
knivil schrieb:
PS: Lass einfach mal die Ausgabe weg.
Wenn der Compiler halbwegs was taugt, kommt dann wahrscheinlich immer annähernd 0 raus
Nicht wenn er die Werte alle ausgibt, oder denkst du der berechnet das zur Compile-Time?
MfG SideWinder
-
Nachdem ich aus dem Programm korrektes C gemacht habe (beispielsweise <ctime> gibt es nicht in C - nur C++), habe ich es auch mal ausprobiert. Bei mir läuft das Programm so knapp 4 Sekunden. Allerdings habe ich die Ausgabe nach /dev/null umgeleitet. Offensichtlich sind die restlichen 2445 Sekunden dazu da, die Ausgabe auf dem Bildschirm zu machen.
Das java-Programm braucht bei mir 90,5 Sekunden. Auch mit umgeleiteter Ausgabe.
Gcc liegt in der Version 4.4.1 und java als sun-jdk 1.6.0 vor. Beide Varianten liefen unter Ubuntu 9.10 auf einer 2GHz AMD-CPU.
-
SideWinder schrieb:
maximAL schrieb:
knivil schrieb:
PS: Lass einfach mal die Ausgabe weg.
Wenn der Compiler halbwegs was taugt, kommt dann wahrscheinlich immer annähernd 0 raus
Nicht wenn er die Werte alle ausgibt, oder denkst du der berechnet das zur Compile-Time?
MfG SideWinder
Nochmal lesen?
-
tntnet schrieb:
Bei mir läuft das Programm so knapp 4 Sekunden. Allerdings habe ich die Ausgabe nach /dev/null umgeleitet. Offensichtlich sind die restlichen 2445 Sekunden dazu da, die Ausgabe auf dem Bildschirm zu machen.
wahrscheinlich hast du recht, ich hab die ausgabe gegen folgendes ersetzt:
volatile char *vp; volatile int vi; void dummy (char *p, int i) { vp = p; vi = i; }
^^ in der hoffnung, dass der compiler die schleife nicht rauswirft (was er offenbar nicht tut)
resultat: 3 Sekunden.tntnet schrieb:
Das java-Programm braucht bei mir 90,5 Sekunden. Auch mit umgeleiteter Ausgabe.
dem Java-programm hab ich eine ähnliche funktion untergejubelt:
static volatile int vi; static void dummy (int i) { vi = i; }
und jetzt - gut festhalten - 779 Millisekunden
erklärung? keine ahnung, vielleicht ist der java-compiler schlauer und macht aus der rekusiven fak()-funktion was iteratives.
-
779 ohne VM-Startup oder mit? Evtl. hat der JIT-Compiler auch zur Laufzeit die Sinnlosigkeit erkannt und rausgeworfen? Ist es *fix*, dass er volatile niemals nie optimieren darf in Java?
MfG SideWinder
-
Den C/C++ Code bitte mit VC++ kompilieren, das Resultat ist praktisch immer schneller als MinGW/G++ Erzeugnisse
Gewisse Komplexität vorausgesetzt natürlich.
-
SideWinder schrieb:
779 ohne VM-Startup oder mit?
ohne, ich hab den originalcode genommen, nur System.out.println() gegen dummy() ersetzt.
SideWinder schrieb:
Evtl. hat der JIT-Compiler auch zur Laufzeit die Sinnlosigkeit erkannt und rausgeworfen? Ist es *fix*, dass er volatile niemals nie optimieren darf in Java?
wer weiss? dieses java-zeug ist ja sehr intelligent und macht laufzeitoptimierungen, etc. vielleicht hat es einige abkürzungen genommen (es gibt keinen zweiten thread, der auf die volatile-variable zugreift, also mach' ich mal nix), aber das glaube ich nicht. 'volatile' verhält sich ähnlich wie 'synchronized' oder volatile in C: die variable muss sofort beschrieben, und darf nicht gecached werden. wenn ich die schleife auskommentiere, braucht er 0 ms, also irgendwas wird er schon machen.
Icematix schrieb:
Den C/C++ Code bitte mit VC++ kompilieren, das Resultat ist praktisch immer schneller als MinGW/G++ Erzeugnisse
Gewisse Komplexität vorausgesetzt natürlich.ha, mein fehler. ich hab im debug-mode compiliert. im release-mode (VS 2005) und 'clock' gegen GetTickCount() ersetzt sind es nur noch: 502 Millisekunden
ok, die welt ist wieder in ordnung: C ist etwas schneller. uff, ich hab' schon 'nen schreck gekriegt.
-
Also bei mir sieht es mit dummy Funktionen so aus:
MmingW 4.2.1 (64 Bit): 232 ms
Java 1.6 (32 Bit): 254-262 ms
MmingW 4.2.1 (32 Bit): 268 ms
VC++ 2008 prof (64 Bit): 265-281 ms
VC++ 2008 prof (32 Bit): 327-344 msBei MingW mit -O2 und -fomit-frame-pointer. Bei VC++ mit /O2 /Ot /Oy (Rest belassen wie es war). Sollten also so ca. die gleichen Vorraussetzungen sein.
Java 64 Bit kann ich leider nicht testen.
Die Zeiten schwanken aber deutlich und liegen so nah aneinander das man da kaum genaue Vergleiche ziehen kann.
-
Ein Vergleich von C# vs. Java wäre sinnvoller.
Ich tippe mal, das Java C# Sharp um Längen wegfegen wird.
-
Solche Microbenchmarks sind doch sinnlos. Erstrecht wenn man sie so stümperhaft ausführt :).
Aber wenn schon, dann http://shootout.alioth.debian.org/u64/benchmark.php?test=all&lang=all
-
SideWinder schrieb:
[...] Ist es *fix*, dass er volatile niemals nie optimieren darf in Java?
Nö, steht nirgendwo das er das nicht darf. Volatile wird eigentlich auch nur
für Multithreading verwendet und dort muss dann garantiert sein das die als
volatile gekennzeichnete Variable für alle Threads sichtbar ist und einen
konsistenten Wert enthält. Kann gut sein, das wenn die Variable nur im main-
Thread deklariert ist und nirgendwo anders verwendet wird, der Compiler das
wegoptimiert.Java-Programme kann man im Allgemeinen nicht so benchmarken wie C-Programme.
Die ersten drei einfachen Sachen sind zuerst mit dem javac und optimize flag
kompilieren. Eclipse hat z.B. seinen eigenen Builder.
Die JVM mit -server starten, für eine noch strengere Codeoptimierung während
der Laufzeit.
Und als dritte Maßnahme nie benchmarken ohne Warm-up (ein paar Minuten), damit
der dynamische Compiler eine Chance hat VOR dem eigentlichen Benchmark zu
optimieren oder gar Code in nativen Maschinencode umzuwandeln und nicht während
des Benchmarks.
Desweiteren muss man auch schauen was der GC so treibt und vielleicht den
Speicher erhöhen damit er nicht während des Benchmarks aktiv wird.Das größte Problem beim benchmarken ist sowieso zu verhindern das der
Benchmarkcode als "toter Code" erkannt wird.
-
rüdiger schrieb:
Solche Microbenchmarks sind doch sinnlos. Erstrecht wenn man sie so stümperhaft ausführt.
garnicht, die zeigen zumindest, dass der zeitliche unterschied bei reiner codeausführung zwischen Java und C viel kleiner ist, als die meisten glauben. C ist zwar schneller, aber nicht viel. (die von dir verlinkte seite zeigt das ja auch).
-
garnicht ... zwischen Java und C viel kleiner ... verlinkte seite zeigt das ja auch
Mir zeigt diese Seite in erster Linie, dass Java im Vergleich zu C++ abkackt.
-
und...wtf im Vergleich zu Haskell!
Das hätte ich ja nie gedacht. Krasse Sache das.
-
knivil schrieb:
garnicht ... zwischen Java und C viel kleiner ... verlinkte seite zeigt das ja auch
Mir zeigt diese Seite in erster Linie, dass Java im Vergleich zu C++ abkackt.
...und machmal gewinnt sogar Javascript *fg*.
bei den zweifelhaften tests auf der seite sind überall noch ausgaberoutinen (printf usw.) mit drin, die das ergebnis verfälschen können. die haben wir hier wenigstens rausgeschmissen. bei uns stört nur noch das multitasking des OS.
-
Der Vergleich bringt doch nichts. Ein interpretierter Code und sei es der feinste Bytecode in einer hochoptimierten Runtime wird niemals die Performance von Nativ-Code erreichen. Und was von dieser physikalischen Hürde übrig bleibt, liegt im Geschick des Programmierers.
-
Cpp_Junky schrieb:
Der Vergleich bringt doch nichts. Ein interpretierter Code und sei es der feinste Bytecode in einer hochoptimierten Runtime wird niemals die Performance von Nativ-Code erreichen.
^^deswegen macht Java ja auch aus zeitkritischen abschnitten maschinencode (und hat dabei mehr optimierungsmöglichkeiten als ein C compiler, dessen output statisch ist) http://en.wikipedia.org/wiki/Adaptive_optimization
gut gemachte C-programme wird java geschwindigkeitsmässig wohl trotzdem nie überholen, aber möglichst nah ranzukommen ist ja auch schon was wert.
-
Cpp_Junky schrieb:
Der Vergleich bringt doch nichts. Ein interpretierter Code und sei es der feinste Bytecode in einer hochoptimierten Runtime wird niemals die Performance von Nativ-Code erreichen. Und was von dieser physikalischen Hürde übrig bleibt, liegt im Geschick des Programmierers.
Doch, denn:
[...]adaptive optimization may take advantage of local data conditions to optimize away branches and to use inline expansion to decrease context switching.
Siehe auch: http://en.wikipedia.org/wiki/Java_performance#Other_optimization_techniques
-
TheTester schrieb:
Das größte Problem beim benchmarken ist sowieso zu verhindern das der
Benchmarkcode als "toter Code" erkannt wird.Das größte Problem beim benchmarken ist es, dass es vollkommen Sinnlos ist. Wenn du beide Sprachen schon vergleichen willst, dann bitte baue auch in C einen Exceptions, GC, Threads, OOP usw. usf. ein, das was du in Java schon alles zur Verfügung hast.
Dann kannst du erst C und Java vergleichen und ich garantiere dir, dass Java wesentlich schneller oder gleich mit C sein wird, denn ich bezweifle, dass du die Java Sprachfeatures besser implementieren kannst als es die Sun-Leute können.
-
DEvent schrieb:
TheTester schrieb:
Das größte Problem beim benchmarken ist sowieso zu verhindern das der
Benchmarkcode als "toter Code" erkannt wird.Das größte Problem beim benchmarken ist es, dass es vollkommen Sinnlos ist. Wenn du beide Sprachen schon vergleichen willst, dann bitte baue auch in C einen Exceptions, GC, Threads, OOP usw. usf. ein, das was du in Java schon alles zur Verfügung hast.
Dann kannst du erst C und Java vergleichen und ich garantiere dir, dass Java wesentlich schneller oder gleich mit C sein wird, denn ich bezweifle, dass du die Java Sprachfeatures besser implementieren kannst als es die Sun-Leute können.
Das wäre so richtig sinnlos. Es klingt so als würde man C und Lisp nur vergleichen können wenn man in C alles wie in Lisp machen würde. Dass das totaler Schwachsinn ist hätte sogar dir auffallen müssen...
Ein sinnvoller Vergleich von zwei Sprachen ist imho nur möglich wenn das gleiche Problem mit den gleichen Algorithmen bearbeitet wird, aber in einem für die jeweiligen Sprachen üblichen/guten Stil. Das ist wohl auch der Grund warum solche Vergleiche auch nur auf minimale Probleme anwendbar sind, da man dies bei größeren Programmen kaum noch garantieren kann.