Java vs. C. Performance-Vergleich
-
das os cached von der platte gelesene daten in ram.
-
KingKarl schrieb:
Steffo schrieb:
Vielleicht kennt jemand eine perfomantere C-Implementierung?
Werde ich später mal ausprobieren, danke.
-
Steffo schrieb:
Die Vorgehensweise ist doch bei beiden gleich: Erst die Datei komplett in einen Buffer lesen und dann auf einen Schlag schreiben.
wo hast das gelesen? kennst du die implementation von obj.transferTo?
-
Probier mal http://msdn.microsoft.com/en-us/library/windows/desktop/aa363851(v=vs.85).aspx
Und wenn du die Geschwinigkeiten irgendwie ernsthaft vergleichen willst, dann nimm nur Lese oder Schreibgeschwindigkeit. Aber auch das dürfte nicht sonderlich spannend sein. Das ist einfach nur ein Aufruf, und der limitierende Faktor ganz klar die Festplatte*. Streng genommen kann man schon sehen, dass irgendwo ein Fehler sein muss, sobald man stark abweichende Ergebnisse bekommt.
Wenn du die Geschwindigkeiten vergleichen willst, dann nimm irgendetwas mit vielen Rechenoperationen und Speicherzugriffen. Parsing, Lineare Algebra, ...
Edit:
* Und nein, das ist nicht das gleiche Argument wie "sonst misst man ja nur die CPU". Es geht ja eben darum zu schauen, mit welcher Sprache man die CPU optimaler ansprechen kann. Bei dem Festplattenzeugs hier wird aber ziemlich simpel ein Befehl ans System gesendet und das wars dann. Da haben die Sprachen nicht viel mit zu tun.
-
KingKarl schrieb:
Steffo schrieb:
Die Vorgehensweise ist doch bei beiden gleich: Erst die Datei komplett in einen Buffer lesen und dann auf einen Schlag schreiben.
wo hast das gelesen? kennst du die implementation von obj.transferTo?
schau mal was in der doku steht...
FileChannel.transferTo...
This method is potentially much more efficient than a simple loop that reads from this channel and writes to the target channel. Many operating systems can transfer bytes directly from the filesystem cache to the target channel without actually copying them.
-
Damit wurde bewiesen, dass mit java sehr wohl I/O-Benchmarks geschrieben werden können, wenn die Dateien gross genug sind. Benchmarking ist nicht so einfach. Schau mal hier:
$ time java Copy copy_c foo
real 0m0.061s
user 0m0.045s
sys 0m0.015s$ time ./copy_c copy_c foo
Größe: 8695real 0m0.002s
user 0m0.002s
sys 0m0.000sDamit kann ich beweisen, dass das C-Programm 2 Millisekunden braucht, das Java-Programm aber 61. Also ist C um den Faktor 30,5 schneller - oder? Oder beweist das, dass ein Java Programm einfach ca. 30 mal so lange braucht, bis es los läuft? Oder beweist das eher, dass der Vergleich Java vs. C mit einem I/O-Benchmark nicht wirklich entschieden werden kann?
-
tntnet schrieb:
...dass der Vergleich Java vs. C mit einem I/O-Benchmark nicht wirklich entschieden werden kann?
da gibts nichts zu entscheiden! es gibt nichts schnelleres als der cpu zu geben was sie braucht und das ist kein java.
-
OK, ich kann nun wieder Entwarnung geben.
Wenn ich das OS-spezifische(!) sendfile aufrufe, braucht esreal 0m1.294s
user 0m0.000s
sys 0m1.279sNochmals zur Erinnerung:
Java braucht:
real 0m1.415s
user 0m0.124s
sys 0m1.278sAber gut: Wie einige schon angemerkt haben, lässt sich mit Betriebssystemaufrufen nicht wirklich gute Benchmarks messen.
L. G.
SteffoPS:
Hier der Code:
#include <stdio.h> /* fprintf */ #include <string.h> /* strerror */ #include <stdlib.h> #include <sys/sendfile.h> #include <fcntl.h> /* open, O_RDONLY, O_WRONLY, O_CREAT, O_EXCL */ #include <sys/stat.h> /* mode_t, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH */ #include <unistd.h> /* read, write */ #include <errno.h> /* errno */ int main(int argc, char *argv[]) { const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; /* rw-r--r-- */ int in, out; /* Dateideskriptoren */ off_t *offset = NULL; unsigned int size; struct stat buf; if (argc != 3) { fprintf(stderr, "Aufruf: %s Quelle Ziel\n", argv[0]); return 1; } in = open(argv[1], O_RDONLY); if (in == -1) { fprintf(stderr, "Quelle %s kann nicht geoeffnet werden (errno %d: %s)\n", argv[1], errno, strerror(errno)); return 1; } if (fstat(in, &buf) == -1) { fprintf(stderr, "Es konnten keine Informationen aus Quelle '%s' ausgelesen werden (errno %d: %s)\n", argv[1], errno, strerror(errno)); return 1; } size = buf.st_size; out = open(argv[2], O_WRONLY | O_CREAT | O_EXCL, mode); if (out == -1) { fprintf(stderr, "Ziel %s kann nicht erzeugt werden (errno %d: %s)\n", argv[2], errno, strerror(errno)); return 1; } if ( sendfile(out, in, offset, size) == -1) { fprintf(stderr, "Ziel %s kann nicht geschrieben werden (errno %d: %s)\n", argv[1], errno, strerror(errno)); return 1; } close(out); close(in); return 0; }
-
danke für die mühe
-
Steffo schrieb:
OK, ich kann nun wieder Entwarnung geben.
Wenn ich das OS-spezifische(!) sendfile aufrufe, braucht esreal 0m1.294s
user 0m0.000s
sys 0m1.279sNochmals zur Erinnerung:
Java braucht:
real 0m1.415s
user 0m0.124s
sys 0m1.278sIch frag mich gerade, ob du die Zeiten überhaupt interpretieren kannst? Dass beide Programme für die Aufgabe die gleiche Zeit brauchen 0m1.279s == 0m1.278s
und der Startup der JVM 0m0.124s einfach ein strich in deine Rechnung setzt.
-
Ist sys nicht einfach nur der Systemaufruf und real die Summe von sys und user?
-
Steffo schrieb:
Ist sys nicht einfach nur der Systemaufruf und real die Summe von sys und user?
Eben. Und der sys-Aufruf ist bei dir bei beiden gleich lang, ist ja auch der gleiche Aufruf. Das C Programm braucht aber unmessbar kurz, um den Aufruf an sich durchzuführen, während die Java-VM 0.124s dazu braucht. Da Javasystemaufrufe ebenfalls unmessbar schnell gehen sollten, wird das wohl die Zeit sein, die die VM an sich zum Starten braucht. Das ist also die Zeit, die selbst bei Benchmarks von C-Befürwortern normalerweise rausgerechnet wird, da das doch ein bisschen unfair wäre (und sie es auch gar nicht nötig haben).
Du hast somit gezeigt:
1. Java und C Systemaufrufe sind die gleichen Systemaufrufe. Überraschung!
2. Java läuft in einer VM die eine gewisse Startzeit hat. Überraschung!
-
vllt. halten wir noch fest, dass die webseite der dab bank in java programmiert ist
-
Ich habe übrigens mal mit einem Shell-skript eine Datei kopiert. Damit ging es in etwa genauso schnell, wie mit Java. Also sind shell-skripte genauso schnell wie Java. Dabei dachte ich, so interpretiertes Zeugs, wie shell-skripte sollten doch langsamer sein.
-
ich bins schrieb:
Ich habe übrigens mal mit einem Shell-skript eine Datei kopiert. Damit ging es in etwa genauso schnell, wie mit Java. Also sind shell-skripte genauso schnell wie Java. Dabei dachte ich, so interpretiertes Zeugs, wie shell-skripte sollten doch langsamer sein.
Da ist ja auch die Festplatte und das Dateisystem das Bottleneck, nicht der Code