Wie, sehr schnell, Daten auf Festplatte schreiben?!?
-
Hallo,
wir müssen für ein Projekt in der BA einige kleine Performancetests machen(nichts aufregendes, es gehts um Prinzip und erkennen von Schwachstellen) und hab nun folgenden Code z.B.
#include <iostream> #include <fstream> using namespace std; static int main() { const int anzahl = 5000000; int* feld = new int[anzahl]; fstream File("data.dat",ios::out|ios::binary); if(File.is_open()) { for(int i = 0; i < anzahl; i++) { File.write((const char*)&feld[i],sizeof(int)); } } File.close(); return 0; }Der erscheint mir aber nicht sehr effektiv

Welche Daten auf die Platte geschrieben werden ist egal, kommt nur auf die Größe an, die ich irgendwo steuern können muss(in dem Fall durch die Anzahl der Elemente im Array). Aber gibt es schnellere Möglichkeiten sowas zu realisieren? Weil momentan kommt mir des nen bissle arg langsam vor wenn er für knapp 20MB fast 30 Sekunden brauch.
Wäre für jeden kleinen Tipp dankbar
mfg
-
warum machst du denn nicht write(alles auf einmal);
-
BA achtet auf Performance??

[EDIT] Tschuldigung fpür sinnlos Post [/EDIT]
-
Und wie? C++ ist normalerweise net so mein Fall

Hab aber auch gesehen, das es durch den Release Mode um einiges schneller ist, hätte nicht gedacht dass es durch den Debug Mode so ausgebremst wird.
-
File.write((const char*)&feld[0],sizeof(int) * anzahl);
so ungefähr.
-
#include <iostream> #include <fstream> using namespace std; static int main() { const int anzahl = 5000000; int* feld = new int[anzahl];//vermeide das. kann vorkommen, daß //dein prog ausgelagert werden muss deshalb. also verbietet sich auch, //20MB mit new anzulegen und auf einmal rauszupusten. fstream File("data.dat",ios::out|ios::binary); if(File.is_open()) { //nee. if(!File) return 1; for(int i = 0; i < anzahl; i++) { File.write((const char*)&feld[i],sizeof(int)); //viel zu kleine schreib-einheit. //ab 4k ist es gut. nehmen wir einfach mal 64k. größer bringt nix mehr. } } File.close(); return 0; }also
typedef long long i64; i64 anzahl=587456876783; int const BLOCKSIZE=65536; char buffer[BLOCKSIZE]; fstream File("data.dat",ios::out|ios::binary); if(!File) return 1; while(anzahl>=BLOCKSIZE){ File.write(buffer,BLOCKSIZE); anzahl-=BLOCKSIZE; } File.write(buffer,anzahl);iostream ruft irgendwie innendrin schon das synchrone write vom betriebssystem auf. und das ist meiner erfahrung nach auch gut so. experimente mit asyncronem schreiben, WriteFileCluster und filemapping ergaben beim schreiben für mich nie sonderliche performancegewinne.
andererseits, du hast ja hier überhaupt keine verarbeitung, es mag durchaus sein, daß du mit asynchronem schreiben (weil du nix kopieren msst dabei) noch was rausholst. aber der code wird ungleich komplizierter.
-
wenn man jetzt bei write sofort das ganze array übergibt, dann wird die write methode doch für ne gute zerstückelung sorgen (falls sowas überhaupt notwendig ist) oder nicht?
-
Vielen Dank, läuft jetzt schon viel zufriedenstellender als vorher. Deine Kommentare haben auch gleich weitere Fragen von mir erklärt, z.b. wie ich verhindern kann, dass ich die 20MB auf einmal erstellen muss im Speicher, weil mir das Auslagerungsproblem durchaus bewusst ist.
Deine Idee mit den asynchronen Schreiben klingt auch interessant, mal sehen, vielleicht finde ich dazu ja Beispiele die ich nutzen könnte.gruß
-
Aber gerade weil nix nebenbei gearbeitet wird, kann das asynchrone Schreiben doch gar nix bringen.
-
Ringding schrieb:
Aber gerade weil nix nebenbei gearbeitet wird, kann das asynchrone Schreiben doch gar nix bringen.
bei win isses afir so, daß man beim asynchronen schreiben den speicher auf 4k-grenzen ausgerichtet haben muss mit dem zweck, daß das bs diesen speicher direkt nimmt, statt sich erstmal ne kopie des dateninhalts zu holen. man würde einmal kopieren sparen. außerdem kann's ja sein, daß warumauchimmer erstmal was getan werden muss. speicher für den plattencache bereitstellen oder was, bevor der erste block angenommen werden kann. die sorge wären wir auch los, ist doch egal, wann das bs bereit ist, wir sinmd schonmal fertig.
fertig? oh, nein. wir dürfen sicherlich nicht das prog beenden, solange nicht alle schreiboperationen rückmeldung geliefert haben. wir müssen also warten, bis alles auf platte ist. wie schrecklich. ok, lieber synchron schreiben und 50MB vorher aufhören dürfen und uns freuen, daß noch 50MB aus dem plattencache auf die platte wandern, *nachdem* unser programm längst beendet ist. jo, schätze, da läß sich nix nennenswertes mehr rausholen.
-
wenn's so sein soll, dass die daten möglichst schnell auf die platte wandern, dann kann man's unter win mit FILE_FLAG_NO_BUFFERING und FILE_FLAG_WRITE_THROUGH erzwingen. das bedeutet natürlich, dass die anwendung die daten langsamer los wird. das schreiben in den cache geht nun mal schneller
-
Hmm, ich soll ja gerade die Zeit messen die wirklich fü den Festplattenzugriff genutzt wird und nicht die mit dem Cache, also währe das asynchrone Schreiben mit den von net genannten Flags wohl doch die bessere Wahl?!? Zeit messen tu ich übrigens mit QueryPerformanceCounter und QueryPerformanceFrequency, was genaueres gibts ja unter Windows nicht, oder?
-
QueryPerformanceCounter ist genau genug.
Ja, die genannten Flags wären sinnvoll, wobei ich aber bezweifle, dass es sich merkbar auf deinen Messwert auswirkt.