Programmlaufzeitfrage
-
So. Ich hab den Test mit "in.getline(buffer, sizeof(buffer))" gemacht (also ganz ohne std::string - womit wir nun endlich genau die selbe Funktionalität verglichen hätten), der ist nun statt Faktor 8.3 etwa Faktor 7.5 langsamer.
BTW: dass die "ios_base::binary und alles auf einmal lesen" Variante schnell ist ist klar, die verwendet ja auch die iostreams Library für nix anderes als einen grossen Block Daten zu kopieren. Das bringt man mit stdio genauso hin, und sicher auch wieder schneller, wenn auch wahrscheinlich bloss um ein paar Takte.
@Konrad Rudolph: ich hab auch von Anfang an behauptet dass iostreams langsamer sein wird als stdio (lies ein paar Postings weiter oben). Bloss kam dann so ein "dafür gibt es garkeinen Grund" Kommentar. Ob es einen Grund gibt hin oder her, auf jeden Fall ist es so, und ich sah mich genötigt das zu demonstrieren.
-
Plotzenhotz schrieb:
So. Ich hab den Test mit "in.getline(buffer, sizeof(buffer))" gemacht (also ganz ohne std::string - womit wir nun endlich genau die selbe Funktionalität verglichen hätten), der ist nun statt Faktor 8.3 etwa Faktor 7.5 langsamer.
das ist immernoch unfug.
zeig mal dein endgültiges programm, das unter fairen bedingungen <cstdio> mit <fstream> vergleicht und faktor 7.5 schneller ist. ich gebe mir ausnahmsweise die mühe, es zu verreißen, da du mir in anderen threads deutlich als ahnunghaber und hilfsbereiter aufgefallen bist.
-
Das ganze vergleichen hier ist doch Bullshit Leute !
Und auch noch Faktoren rausgeben wollen, was die clib schneller ist wie eine IOStream impl?Jeder der mit streams arbeitet, weiss das er es ned wegen der geschwindigkeit tut. Wenn man sagt das c++ performant sein kann/soll, meint man in c++ auch so programmieren kann, das die geringfuegig geringere performance kein Grund sein soll die anderen vorteile von c++, der stl und dem stream konzept ueber boartd zu werfen !
Und wenn ich wirklich auf speed aus bin bei dateioperationen ( Bitte welchem vernunftigen Programmierer intressiert nen minimaler performanceverlust bei dateioperationen auf nem multhithreading/multiprocessing BS ??? ) aus bin, werd ich doch zuerst mein BS konsultieren (Posix, winapi) und die streams / filebuffer bei seite legen ...
Ciao ...
-
ich lass jetzt mal das hier dorchlaufen:
#include <iostream> #include <cstdio> #include <fstream> #include <string> using namespace std; #define g_inputFileName "test.txt" #define gc_lineCount 100000000 void CreateTestFile() { FILE* outFile = fopen(g_inputFileName, "w"); if(!outFile) abort(); for(size_t i = 0; i < gc_lineCount; i++) { int r = rand() % 3; char const* s = 0; switch(r) { case 0: s = "Bla, Bloe\n"; break; case 1: s = "Ding, Dong\n"; break; case 2: s = "X, Y\n"; break; } fputs(s, outFile); } fclose(outFile); } int countLineNumbers1(){ int result=0; FILE* inFile = fopen(g_inputFileName, "r"); if(!inFile) abort(); char buffer[1024]; while(fgets(buffer, sizeof(buffer), inFile)) ++result; fclose(inFile); return result; } int countLineNumbers2(){ int result=0; ifstream inFile(g_inputFileName);//edit: hier war fehlerhaft ios::binary if(!inFile) throw 4711; char buffer[1024]; while(inFile.getline(buffer,1024)) ++result; return result; } int countLineNumbers3(){ int result=0; ifstream inFile(g_inputFileName,ios::binary); if(!inFile) throw 4711; string buffer; while(getline(inFile,buffer)) ++result; return result; } int main() { CreateTestFile(); for(int i=0;i<10;++i) { { clock_t start=clock(); cout<<1<<' '<<countLineNumbers1()<<' '; cout<<(clock()-start)/double(CLOCKS_PER_SEC)<<endl; } { clock_t start=clock(); cout<<2<<' '<<countLineNumbers2()<<' '; cout<<(clock()-start)/double(CLOCKS_PER_SEC)<<endl; } { clock_t start=clock(); cout<<3<<' '<<countLineNumbers3()<<' '; cout<<(clock()-start)/double(CLOCKS_PER_SEC)<<endl; } } return 0; }
das zählt einfach nur die zeilen einer ca 1G großen (einstellbar) datei.
ausgabe:
1 100000000 19.906 2 100000000 19.734 3 100000000 36.516 1 100000000 19.765 2 100000000 19.735 3 100000000 36.703 1 100000000 19.75 2 100000000 19.875 3 100000000 36.469 1 100000000 19.75 2 100000000 19.968 3 100000000 36.313 1 100000000 19.859 2 100000000 19.672 3 100000000 36.188
ich denke mal, an dem ergebnis gibts wenig zu interpretieren. string ist lahm. fstream und iostream sind gleich schnell.
-
@volkard
Welchen Compiler bzw. welche Standard-Lib verwendest du? Erhalte mit dem VC 8 andere Ergebnisse:1 10000000 1.922 2 10000000 5.734 3 10000000 7.891 1 10000000 1.906 2 10000000 5.687 3 10000000 7.891 [...]
Dateigröße war ca. 100 MB.
-
Plotzenhotz schrieb:
So. Ich hab den Test mit "in.getline(buffer, sizeof(buffer))" gemacht (also ganz ohne std::string - womit wir nun endlich genau die selbe Funktionalität verglichen hätten), der ist nun statt Faktor 8.3 etwa Faktor 7.5 langsamer.
die selbe funktionalität reicht aber nicht. wenn man wie Helmut S. die c-variante einigermaßen annehmbar implementiert aber die c++-variante wie der letzte gamecoder vergurkt, ist der vergleich nicht fair.
ich hab auch nicht gerafft, warum man für
//so oder so ähnlich war's doch while(in.getline(file,buffer))&&in.getline(file,buffer)) out.write(buffer);
ein mords brimboriom (unübersichtlich, unnötig, lahm) mit ner klasse namens doppelzeile machen muss.
-
HumeSikkins schrieb:
@volkard
Welchen Compiler bzw. welche Standard-Lib verwendest du? Erhalte mit dem VC 8 andere Ergebnisse:MinGW
D:\source\filetest>g++ -v Reading specs from C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/specs Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host= mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable -languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --e nable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-ja va-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchroniz ation --enable-libstdcxx-debug Thread model: win32 gcc version 3.4.2 (mingw-special)
1 10000000 1.922 2 10000000 5.734 3 10000000 7.891 1 10000000 1.906 2 10000000 5.687 3 10000000 7.891 [...]
Dateigröße war ca. 100 MB.
jo, dann ist die ms-lib wiedermal buggy.
hab jetzt auch mit ms gemessen.1 100000000 25.219 2 100000000 52.703 3 100000000 67.984
-
Hat noch jemand einen älteren VC installiert? Mich würde mal interessieren, wie die nicht-standard-IOStreams abschneiden. Also <iostream.h> und <fstream.h> statt
<iostream> und <fstream>.
-
das ist immernoch unfug.
zeig mal dein endgültiges programm, das unter fairen bedingungen <cstdio> mit <fstream> vergleicht und faktor 7.5 schneller ist. ich gebe mir ausnahmsweise die mühe, es zu verreißen, da du mir in anderen threads deutlich als ahnunghaber und hilfsbereiter aufgefallen bist.Mein endgültiges Programm zeig ich heut' Abend her, sitz grad noch in der Arbeit. Ich bitte nur meine Postings in diesem Thread im Kontext zu sehen, die "Doppelzeile" Sache z.B. stammt nicht von mir, hab ich nur übernommen um zu zeigen dass die auch nicht schneller ist als die "einfache" (normale) Variante. Da ich mich mit iostreams noch nicht SO angefreundet habe wusste ich auch schlichtweg nicht dass getline() mit char* Buffer verfügbar ist, daher hab ich nen std::string genommen. Egal. Meine Erfahrung ist dass iostreams deutlich langsamer sind, so ziemlich egal was man macht. Mag daran liegen dass die MSVC Variante mies implementiert ist. Wie gesagt später mehr.
Und eine Frage gleich vorweg: wie bitte ist "ios::binary" mit fopen(..., "r") zu vergleichen fair? Wenn dann bitte "ios::binary" mit fopen(..., "rb") vergleichen, sonst brauchen wir über fair gleich garnicht zu sprechen. Dass es auf UNIX systemen keinen Unterschied macht ist mir dabei egal, bei MSVC z.B. macht es einen Unterschied. Da es hier aber um Textfiles geht denke ich sollten wir beim "r" und ohne "ios::binary" bleiben. Auf jeden Fall entweder beide binary oder beide als Text Stream.
-
Plotzenhotz schrieb:
Und eine Frage gleich vorweg: wie bitte ist "ios::binary" mit fopen(..., "r") zu vergleichen fair?
ups, das war noch aus versehen drin. hab allerlei verstellt und probiert, um rauszufinden, wie ihr auf die lahmen ergebnisse kommt. ios::binary gehört da nicht rein und macht aber auch keinen unterschied, hoffe ich.
edit: doch, macht anscheinend deutlichen unterschied. muss ich heut abend ausmessen.
-
@volkard:
So. Forum geht wieder (was warn da los?). Gut.
Hab mich nu noch etwas rumgespielt und ein paar kleine Fallstricke für die iostreams entfernt. u.a. das "std::endl" durch '\n' ersetzt und zurück zu MSVC 7.1 da die meiste Zeit bei der MSVC 8 Version beim locking/unlocking diverser critical sections draufgegangen ist (mehrmals pro "getline" Aufruf - daher auch die wüst groben Unterschiede zur stdio Version). Und MSVC 8 hat leider keine single threaded runtime mehr. Neuer Code:#define _WIN32_WINNT 0x0501 #include <windows.h> #include <mmsystem.h> #undef min #undef max #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <time.h> #include <iostream> #include <fstream> #pragma comment(lib, "winmm") static const char* const gc_inputFileName = "c:\\in.txt"; static const char* const gc_outputFileName = "c:\\out.txt"; static const size_t gc_lineCount = 160*1000; void CreateTestFile() { FILE* outFile = fopen(gc_inputFileName, "w"); if(!outFile) abort(); for(size_t i = 0; i < gc_lineCount; i++) fputs("123456789012345678901234\n", outFile); fclose(outFile); } void ReadInputFileStdio() { FILE* inFile = fopen(gc_inputFileName, "r"); if(!inFile) abort(); char buffer[1024]; while(fgets(buffer, sizeof(buffer), inFile)) ; fclose(inFile); } void ReadInputFileIostream() { std::ifstream in(gc_inputFileName); char buffer[1024]; while(in.good()) in.getline(buffer, sizeof(buffer)); } size_t TestStdio() { FILE* inFile = fopen(gc_inputFileName, "r"); if(!inFile) abort(); FILE* outFile = fopen(gc_outputFileName, "w"); if(!outFile) abort(); size_t outLines = 0; char buffer[1024]; while(1) { if(!fgets(buffer, sizeof(buffer), inFile)) break; if(!fgets(buffer, sizeof(buffer), inFile)) break; if(fputs(buffer, outFile) < 0) abort(); outLines++; } fclose(inFile); fclose(outFile); return outLines; } size_t TestIostream3() { std::ifstream in(gc_inputFileName); std::ofstream out(gc_outputFileName); char buffer[1024]; size_t outLines = 0; while(1) { if(!in.getline(buffer, sizeof(buffer))) break; if(!in.getline(buffer, sizeof(buffer))) break; out << buffer << '\n'; outLines++; } return outLines; } int main(int argc, char** argv) { CreateTestFile(); if(::timeBeginPeriod(1) != TIMERR_NOERROR) abort(); size_t outLineCount = 0; DWORD t0, t1; // TestStdio for(unsigned rep = 0; rep < 5; rep++) { ::DeleteFileA(gc_outputFileName); ReadInputFileStdio(); ReadInputFileStdio(); printf("TestStdio: "); t0 = ::timeGetTime(); outLineCount = TestStdio(); t1 = ::timeGetTime(); printf("Lines: %ld, time: %ld msec\n", long(outLineCount), long(t1 - t0)); } // TestIostream3 for(unsigned rep = 0; rep < 5; rep++) { ::DeleteFileA(gc_outputFileName); ReadInputFileIostream(); ReadInputFileIostream(); printf("TestIostream3: "); t0 = ::timeGetTime(); outLineCount = TestIostream3(); t1 = ::timeGetTime(); printf("Lines: %ld, time: %ld msec\n", long(outLineCount), long(t1 - t0)); } ::timeEndPeriod(1); printf("\nPress any key to continue.\n"); getch(); }
Ergebnis (Pentium 4 Northwood, 2.8GHz, XP SP2):
TestStdio: Lines: 80000, time: 66 msec TestStdio: Lines: 80000, time: 66 msec TestStdio: Lines: 80000, time: 66 msec TestStdio: Lines: 80000, time: 66 msec TestStdio: Lines: 80000, time: 67 msec TestIostream3: Lines: 80000, time: 111 msec TestIostream3: Lines: 80000, time: 105 msec TestIostream3: Lines: 80000, time: 107 msec TestIostream3: Lines: 80000, time: 108 msec TestIostream3: Lines: 80000, time: 112 msec Press any key to continue.
Nu ham wir 66 vs. 105 msec.
Ohne output:TestStdio: Lines: 80000, time: 34 msec TestStdio: Lines: 80000, time: 32 msec TestStdio: Lines: 80000, time: 33 msec TestStdio: Lines: 80000, time: 32 msec TestStdio: Lines: 80000, time: 45 msec TestIostream3: Lines: 80000, time: 71 msec TestIostream3: Lines: 80000, time: 70 msec TestIostream3: Lines: 80000, time: 69 msec TestIostream3: Lines: 80000, time: 69 msec TestIostream3: Lines: 80000, time: 90 msec Press any key to continue.
Also 32 vs. 69 msec. Viel besser als mit MSVC 8, aber iostreams immer noch langsamer. Falls ich da jetzt immer noch nen "Fehler" (eine "Bremse") in der iostream Implementierung drin habe bitte gerne mich darauf hinzuweisen.
"Selber Code" mit MSVC6, <iostream.h> und <fstream.h> (std:: entfernt, die liegen beim MSVC 6 im global namespace, und "rep" vor den Schleifen definiert, weil MSVC 6 for-scope-bug, sonst keine Änderung). Optimiert für Pentium-Pro, inlining aktiviert, single-threaded Runtime, ... . R/W:
TestStdio: Lines: 80000, time: 72 msec TestStdio: Lines: 80000, time: 70 msec TestStdio: Lines: 80000, time: 68 msec TestStdio: Lines: 80000, time: 69 msec TestStdio: Lines: 80000, time: 69 msec TestIostream4: Lines: 80000, time: 191 msec TestIostream4: Lines: 80000, time: 174 msec TestIostream4: Lines: 80000, time: 184 msec TestIostream4: Lines: 80000, time: 172 msec TestIostream4: Lines: 80000, time: 175 msec Press any key to continue.
R:
TestStdio: Lines: 80000, time: 34 msec TestStdio: Lines: 80000, time: 34 msec TestStdio: Lines: 80000, time: 34 msec TestStdio: Lines: 80000, time: 32 msec TestStdio: Lines: 80000, time: 32 msec TestIostream4: Lines: 80000, time: 126 msec TestIostream4: Lines: 80000, time: 202 msec TestIostream4: Lines: 80000, time: 128 msec TestIostream4: Lines: 80000, time: 124 msec TestIostream4: Lines: 80000, time: 123 msec Press any key to continue.
Andere Compiler hab ich leider keine, STLPORT auch nicht, wäre aber interessant wie schnell die ist.
Und... hast du mit oder ohne MT Support compiliert? Würe mich nur interessieren.
-
Plotzenhotz schrieb:
Und... hast du mit oder ohne MT Support compiliert? Würe mich nur interessieren.
ohne MT.
ich habe ca. 30% overhead für das verwenden von ifstream. da muß ich wohl doch nach c umsteigen.
-
Eiei, wieder ein spitzes Kommentar
Mir ist es im Prinzip wurscht ob irgendwo irgendetwas langsamer/schneller ist. Mich nervt nur wenn jmd. sowas wie die iostream vs. stdio hernimmt (oder wie gerade eben std::vector vs. malloc+memset) und sich dann wundert dass es langsamer ist. Klar kanns langsamer sein, macht ja nixe. Genauso nervt es mich aber auch wenn dann jmd. hergeht und behauptet es gäbe garkeinen Grund dass A langsamer als B ist. Kann schon sein dass es keinen guten Grund gibt dass es so sein muss, aber wenns so ist, dann muss man sich einfach damit abfinden. Wenns wichtig ist wo das letzte bisschen an Geschwindigkeit rauszuholen dann schreib' ich das sowieso mit Hand bzw. mache zumindest Tests mit den verschiedensten Sachen. Und wenns nicht wichtig ist nimmt man einfach das was am einfachsten zu schreiben und verstehen ist und fertig.
-
Plotzenhotz schrieb:
Genauso nervt es mich aber auch wenn dann jmd. hergeht und behauptet es gäbe garkeinen Grund dass A langsamer als B ist.
ich sage aber weiterhin: es gibt gar keine notwendigkeit, daß iostream lahmer als stdio ist.
darüberhinaus möchte ich behaupten, daß da anscheinend auf breiter front gepfuscht wird. bei MS kann ich mir ja noch denken, daß es nur drum geht, VB unbd C# schneller aussehen zu lassen. bei gcc weiß ich's nicht. vielleicht sind die vorgaben im standard ja schon so, daß es dafür keine schnelle implementierung geben kann, ohne daß die exe-datei noch 200k größer wird.
-
Ja vielleicht hab ich mich in diesem Thread auch nicht richtig ausgedrückt. Mir ging es alleine um die Feststellung dass die derzeitigen iostreams Implementierungen die ich kenne, und von denen ich diverse Benchmarks im Netz gelesen habe, alle langsamer sind als stdio.
Zu behaupten dass es immer so sein muss war ein Fehler - das kann ich nicht beurteilen ohne den Standard wesentlich besser zu kennen als ich es tue.
-
Plotzenhotz schrieb:
Mir ging es alleine um die Feststellung dass die derzeitigen iostreams Implementierungen die ich kenne, und von denen ich diverse Benchmarks im Netz gelesen habe, alle langsamer sind als stdio.
ok.
mir war bekannt, daß cout derzeit überall lahmer ist als printf, obwohl es technische gründe gibt, weshalb cout schneller sein sollte.
jetzt ist mir dank dieses threads zusätzlich bekannt, daß zeilenlesen mit ifstream deutlich lahmer ist als mit FILE*, obwohl es dafür gar keinen technischen grund gibt.
vermutlich hat gar nicht bjarne s. diese sprache erfunden. das war noch mitten im kalten krieg. die russen haben sie erfunden, um die westliche entwicklung der computerwissenschaften lahmzulegen. also sie ist schonmal so kompliziert, daß man selbst als vollprofi libs schreibt, die lahm sind und 10 jahr später noch keiner schnelle libs gebaut hat (im gegenteil, so lahm wie bei ms heute waren sie nie, vermute ich). vielleicht ist nichtmal c++ allein dfas problem, sondern die ganze objektorientierung. java ist ja auch nicht berühmt für schnelle dateifilteroperationen. ich werde das mal beobachten und bei gelegenheit kaufe ich mir in ebay einen 64-er. kann ja sein, daß die entwicklung so weitergeht und ich dann mit dem 64-er schneller bin.
-
Plotzenhotz schrieb:
Ja vielleicht hab ich mich in diesem Thread auch nicht richtig ausgedrückt. Mir ging es alleine um die Feststellung dass die derzeitigen iostreams Implementierungen die ich kenne, und von denen ich diverse Benchmarks im Netz gelesen habe, alle langsamer sind als stdio.
Zu behaupten dass es immer so sein muss war ein Fehler - das kann ich nicht beurteilen ohne den Standard wesentlich besser zu kennen als ich es tue.Wenn du da nen halbwegs fairen Vergleich machen willst musst du direkt mit dem streambuf der Streamklassen arbeiten.
So ist z.B. das gleichwertige C++ Gegenstück zu getc nicht istream::get sondern streambuf::sbumpc.
Die Streamklassen kapseln den Streambuffer und sind vollgestopft mit Status und Fehlercode.Das ist imho zusätzlicher Overhead den die mit sich rum schleppen.Gruß Spacelord
-
@Spacelord: neh, will ich garnicht. Wenn ich irgendwo Speed brauche dann gehe ich "Byte klauben" wie ich das nenne.
@volkard: Ich weiss nicht wie ich deinen Sarkasmus auffassen soll. Hilfreich ist er auf jeden Fall nicht.
-
Plotzenhotz schrieb:
@Spacelord: neh, will ich garnicht. Wenn ich irgendwo Speed brauche dann gehe ich "Byte klauben" wie ich das nenne.
meinste damit ne eigene stream-klasse? so mache ich das auch.
Plotzenhotz schrieb:
@volkard: Ich weiss nicht wie ich deinen Sarkasmus auffassen soll. Hilfreich ist er auf jeden Fall nicht.
nee. hilfreich nicht.
ich denke, die c++-gemeinde muss auch immer wieder aufs neue darüber aufgeklärt werden, daß das standardisierungskomitee keine besseren entscheidungen trifft, als es drei bekiffte gute fachhochschüler in der gleichen zeit täten.
wem hilft dies wissen? niemandem. also nicht hilfreich, wie gesagt. aber ich muß gleichermaßen äußern, daß ich hier ein problem sehe, wie die wahlcomputerfeiglinge dort ein problem sehen.
-
meinste damit ne eigene stream-klasse? so mache ich das auch.
Nö, eine eigene Stream-Klasse hab' ich nu grad nicht, bei mir endet es meist mit spezialisierten Lösungen in denen nicht selten die native API vorkommt (WIN32 halt in meinem Fall). Ich muss ja gottseidank keinen plattformunabhängigen Code schreiben, obwohl ich auch zusehe dass ich die plattformabhängigen Teile irgendwo schön kapseln kann. Mit "Byte klauben" meine ich einfach auf unterster Ebene Code schreiben, selbst "Bytes durch die gegend schieben" etc. Und hätte ich viel mit Textdaten zu tun dann hätte ich wahrscheinlich auch ne eigene Stream-Klasse
ich denke, die c++-gemeinde muss auch immer wieder aufs neue darüber aufgeklärt werden, daß das standardisierungskomitee keine besseren entscheidungen trifft, als es drei bekiffte gute fachhochschüler in der gleichen zeit täten.
wem hilft dies wissen? niemandem. also nicht hilfreich, wie gesagt. aber ich muß gleichermaßen äußern, daß ich hier ein problem sehe, wie die wahlcomputerfeiglinge dort ein problem sehen.Gut. Ich meinte das "weiss nicht wie ich deinen Sarkasmus auffassen soll" nämlich durchaus ernst, hätte ja auch sein können dass du dich über mich oder über das Thema oder sonstwas lustig machst. Mir war also wirklich nicht klar wie ich es auffassen sollte.
Damit dass du dir Luft machen wolltest hab ich kein Problem, das geht mit bei C++ oft genug selbst so. Und über den ollen VC6 könnte ich den ganzen Tag lang schimpfen, ich muss den in der Arbeit noch oft verwenden, und der Grossteil der Libs an denen ich arbeite muss unter VC6 noch laufen