Ungepuffert auf Platte schreiben



  • Hallo ich will am Cache vorbei auf Platte schreiben,
    welche Systemfunktion unter Windows verwendet man da am besten?

    Es soll auch möglichst viel und schnell Daten geschrieben werden.



  • Auch wenn Du am Windows-Cache vorbeikommen würdest, so scheiderst Du vermutlich am eingebauten Cache in der Festplatte.
    Ok, Du kannst natürlich einen eigenen Gerätetreiber für eine spezielle Festplatte schreiben, aber es ist viel sinnvoller seine Anwendung so zu entwerfen, dass man auf solche "Features" nicht angewiesen ist.

    OS mäßig kannst Du es mittels "FILE_FLAG_NO_BUFFERING" bzw. "FILE_FLAG_WRITE_THROUGH" deaktivieren.



  • Jochen Kalmbach schrieb:

    Auch wenn Du am Windows-Cache vorbeikommen würdest, so scheiderst Du vermutlich am eingebauten Cache in der Festplatte.

    Das ist klar, macht auch nichts.

    Jochen Kalmbach schrieb:

    dass man auf solche "Features" nicht angewiesen ist.

    Ich will einfach möglichst flott Daten wegschreiben. Der Systemcache ist da nur ein unnötiger Umweg. Ich schreibe mehrere GByte an Daten auf eine extra Partition, bei jedem neuen Schreibvorgang ist die Part. wieder komplett leer.

    Jochen Kalmbach schrieb:

    OS mäßig kannst Du es mittels "FILE_FLAG_NO_BUFFERING" bzw. "FILE_FLAG_WRITE_THROUGH" deaktivieren.

    Habe mal in der msdn gesucht, da steht was zu meinem Vorhaben.

    Bisher habe ich es eben C++-standardkonform (ein Puffer und den an einen fstream übergeben) gemacht denke aber das ist nicht der schnellste Weg. Hängt auch von der Puffergrösse, der Grösse der Cluster ab. Um einige Experimente werde ich nicht herumkommen.



  • Vor einiger Zeit habe ich mir auch die Frage gestellt welche Methode die schnellste ist. Ich habe verschiedes ausprobiert, über die Api mit und ohne FILE_FLAG_WRITE_THROUGH, mit der stl und ansi. Die stl war mit Abstand am schnellsten die Daten auf die Festplatte zu kriegen (mit verschiedenen Blockgrössen). Leider unterstützt die stl nur Dateien bis 2GB, daher musste ich das ganze mit der Api und FILE_FLAG_NO_BUFFERING implementieren.
    Der Aufwand die Daten mit FILE_FLAG_NO_BUFFERING zu schreiben ist sehr hoch, aber es hat sich gelohnt.



  • lesam schrieb:

    Die stl war mit Abstand am schnellsten die Daten auf die Festplatte zu kriegen

    muss ehrlich sagen: das wundert mich, wo unter windows die stl doch auch nix andres tun kann, als (direkt oder indirekt) die WinAPI zu verwenden!?



  • Ja, diese Frage habe ich mir auch gestellt.
    Hier die Resultate (durchsatz in MB/s):

    (blöcke*blockgrösse)    100*1M 100*(1M+16) 1000*128k 1000*(128k+16) 1000000*128
    api                     37     36          64        63             62 
    FILE_FLAG_WRITE_THROUGH 60     44          59        30             3
    stl                     63     63          62        61             60
    ansi                    39     36          60        -              57
    


  • Ich kann nur sagen: Deine Tests sind falsch. Die STL kann *nie* schneller sein als die WinAPI.
    Vermutlich sind hier Seiteeffekte zu Tage getreten wie MFT-Fragmentation oder sonstwas...



  • Natürlich kann die STL schneller sein, aber wohl eher nur bei kleinen Blockgrössen. Dann muss die STL (weil sie intern schön Puffern kann) weniger API Calls absetzen als wenn man selbst für jeden winzigen Block die API aufruft. Da die API in den Kernelmode wechselt und für jeden Block einen IRP anfordert, diesen ans FS weiterleitet etc. ... kann das schon was bringen.

    Was mich bloss wundert ist dass bei einem 1M block die API ohne "write through" so abstinkt - das kann eigentlich nicht sein, und deckt sich nicht mit dem was ich bis jetzt beobachtet habe. Eigentlich ist "write through" fast immer langsamer... zumidest wenn man es gegen normale writes ohne flush danach vergleicht.

    Der grosse Unterschied zwischen ANSI und STL ist ein weiteres Zeichen dafür dass da irgendwas nicht stimmt -- ich sehe keinen Grund warum die ANSI APIs so extrem langsamer sein sollten.


  • Mod

    hustbaer schrieb:

    Der grosse Unterschied zwischen ANSI und STL ist ein weiteres Zeichen dafür dass da irgendwas nicht stimmt -- ich sehe keinen Grund warum die ANSI APIs so extrem langsamer sein sollten.

    Irgendwas ist hier oberfaul. Schau mal in die Implementierung der STL rein (sofern Du die von MS verwendest). Du wirst festellen, dass die STL wiederum die CRT Library verwendet! Wie sol dieser Umweg auchnoch schneller sein?

    Alle meine Tests zeigen immer wieder das die STL die keimende Kartoffel ist.

    Weiterhin nutzt die CRT nun wieder simpel und einfach die Windows API undmacht keine Tricks, wie auch aus den Sourcen zu sehen ist...

    Ich gehe konform mit Jochen. Ich kann es mir nicht vorstellen.



  • lesam schrieb:

    Vor einiger Zeit habe ich mir auch die Frage gestellt welche Methode die schnellste ist. Ich habe verschiedes ausprobiert, über die Api mit und ohne FILE_FLAG_WRITE_THROUGH, mit der stl und ansi. Die stl war mit Abstand am schnellsten die Daten auf die Festplatte zu kriegen (mit verschiedenen Blockgrössen). Leider unterstützt die stl nur Dateien bis 2GB, daher musste ich das ganze mit der Api und FILE_FLAG_NO_BUFFERING implementieren.
    Der Aufwand die Daten mit FILE_FLAG_NO_BUFFERING zu schreiben ist sehr hoch, aber es hat sich gelohnt.

    Ich schreibe hier mit dem gcc/BCB4 und ofstream die Platte voll, da merke ich nichts von einem 2GB Limit. Das macht sich afaik nur bei FAT32 bemerkbar.

    // C++ - standardkonform
    const unsigned short BUF_SIZE = 512; 
    
    string s(BUF_SIZE,0xFF);
    ofstream file("delme", ios::app|ios::binary);
    while(file.good())
      file.write( s.c_str(),BUF_SIZE);
    
    file << flush;
    file.close();
    

    Je nachdem wie gross BUF_Size ist, geht es ein bischen schneller, ideal ist
    es, wenn der Puffer ein Vielfaches von der Clustersize der NTFS-Partition ist.

    Ich schreibe hier auf eine spezielle Testpartition die leer ist, Fragmentierung macht sich hier also nicht bemerkbar.



  • hustbaer schrieb:

    Der grosse Unterschied zwischen ANSI und STL ist ein weiteres Zeichen dafür dass da irgendwas nicht stimmt -- ich sehe keinen Grund warum die ANSI APIs so extrem langsamer sein sollten.

    Testcode posten, vielleicht steckt da ein Fehler.



  • Diese Tests wurden alle mit der gleichen Festplatte durchführt. Die Festplatte wurde frisch formatiert und es griffen während des Testes keine anderen Programm auf die Festplatte zu. Daher sollte die Resultat auch stimmen. Ein flush wurde übrigens nicht durchgeführt.

    Ich kenne den internen Aufbau der einzelnen Bibliotheken nicht, daher kann ich auch nur raten.
    Die Geschwindigkeiten der api sind in etwa gleich wie bei der ansi, vermutlich greift ansi direkt auf die api zu. Wieso die api bei grossen Blöcken so langsam ist, weiss ich auch nicht.
    Die api ist bei Blockgrössen von 128k am schnellste, das könnte sich ja die stl zu nutzen machen. Es ist auch möglich, dass die stl die Daten selbst puffert und mit FILE_FLAG_NO_BUFFERING schreibt.
    Api mit FILE_FLAG_WRITE_THROUGH ist dann langsam, wenn der Block eine "krumme" Grösse hat (!PAGE_SIZE?).

    CPPWiedereinsteiger schrieb:

    Ich schreibe hier mit dem gcc/BCB4 und ofstream die Platte voll, da merke ich ich nichts von einem 2GB Limit

    Hast du schon mal versucht ein seek auf eine Datei > 2GB zu machen, ohne murks über class fpos?



  • Hier noch was zum selber testen. Ansi habe ich weg gelassen

    #include <iostream>
    #include <fstream>
    #include <cassert>
    #include <vector>
    using namespace std;
    #include <windows.h>
    
    class FileTest
    {
    public:
      virtual unsigned write(__int64 Pos, char *Data, unsigned Count) = 0;
      virtual void flush() = 0;
    };
    
    class FileTestAPI : public FileTest
    {
    public:
      void create(const char *Name)
      {
        //FILE_WRITE_DATA | FILE_READ_DATA
        File = CreateFileA(Name, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        assert(File != INVALID_HANDLE_VALUE);
      }
    
      void createWt(const char *Name)
      {
        File = CreateFileA(Name, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0);
        assert(File != INVALID_HANDLE_VALUE);
      }
    
      void close()
      {
        CloseHandle(File);
      }
    
      void flush()
      {
        FlushFileBuffers(File);
      }
    
      unsigned write(__int64 Pos, char *Data, unsigned Count)
      {
        DWORD CountRet;
        OVERLAPPED Overlapped;
        memset(&Overlapped, 0, sizeof(OVERLAPPED));
        LARGE_INTEGER ToHighLow;
        ToHighLow.QuadPart = Pos;
        Overlapped.Offset = ToHighLow.LowPart;
        Overlapped.OffsetHigh = ToHighLow.HighPart;
        BOOL Success = WriteFile(File, Data, Count, &CountRet, &Overlapped);
        assert(Success);
        return CountRet;
      }
    private:
      HANDLE File;
    };
    
    class FileTestSTL : public FileTest
    {
    public:
      void create(const char *Name)
      {
        File.open(Name, ios::out | ios::in | ios::trunc | ios::binary);
        assert(File);
      }
    
      void close()
      {
        File.close();
      }
    
      void flush()
      {
        File.flush();
      }
    
      unsigned write(__int64 Pos, char *Data, unsigned Count)
      {
        File.seekp(static_cast<streamoff>(Pos));
        File.write(Data, Count);
        assert(File.good());
        return Count;
      }
    private:
      fstream File;
    };
    
    void write(FileTest &FileTest, unsigned NumBlocks, unsigned BlockSize)
    {
      vector<char> Buffer(BlockSize);
      LARGE_INTEGER Freq;
      QueryPerformanceFrequency(&Freq);
      LARGE_INTEGER StartTime;
      QueryPerformanceCounter(&StartTime);
    
      for (unsigned Block = 0; Block < NumBlocks; Block++)
        FileTest.write(Block * BlockSize, &Buffer[0], BlockSize);
      FileTest.flush();
    
      LARGE_INTEGER StopTime;
      QueryPerformanceCounter(&StopTime);
      double Time = static_cast<double>(StopTime.QuadPart - StartTime.QuadPart) / Freq.QuadPart;
      cout << "time = " << Time << "s; tp = " << NumBlocks * BlockSize / Time / 1e6 << "MB/s" << endl;
    
    }
    
    int main()
    {
      const char *FileName = "d:test.dat";
      FileTestAPI Test1;
      Test1.create(FileName);
      cout << "API; number of blocks = 1000; block size = 1M" << endl;
      write(Test1, 1000, 1024*1024);
      cout << "API; number of blocks = 10000; block size = 128k" << endl;
      write(Test1, 10000, 128*1024);
      Test1.close();
    
      FileTestAPI Test2;
      Test2.createWt(FileName);
      cout << "API WT; number of blocks = 1000; block size = 1M" << endl;
      write(Test2, 1000, 1024*1024);
      cout << "API WT; number of blocks = 10000; block size = 128k" << endl;
      write(Test2, 10000, 128*1024);
      Test2.close();
    
      FileTestSTL Test3;
      Test3.create(FileName);
      cout << "STL; number of blocks = 1000; block size = 1M" << endl;
      write(Test3, 1000, 1024*1024);
      cout << "STL; number of blocks = 10000; block size = 128k" << endl;
      write(Test3, 10000, 128*1024);
      Test3.close();
    
      cin.get();
    }
    


  • und noch die Resultate:

    API; number of blocks = 1000; block size = 1M
    time = 45.0773s; tp = 23.2617MB/s
    API; number of blocks = 10000; block size = 128k
    time = 20.2676s; tp = 64.6707MB/s
    API WT; number of blocks = 1000; block size = 1M
    time = 15.7388s; tp = 66.6236MB/s
    API WT; number of blocks = 10000; block size = 128k
    time = 19.9971s; tp = 65.5453MB/s
    STL; number of blocks = 1000; block size = 1M
    time = 24.4787s; tp = 42.8362MB/s
    STL; number of blocks = 10000; block size = 128k
    time = 21.432s; tp = 61.1571MB/s

    Dieser Test wurden auf einem anderen PC durchgeführt als die letzten.



  • lesam schrieb:

    Hast du schon mal versucht ein seek auf eine Datei > 2GB zu machen, ohne murks über class fpos?

    Nein, da das Programm das die Datein weiterverarbeitet nicht von mir ist.
    Ich weiss auch nicht mit welcher Funktion es auf die Daten zugreift, ich habe keinen Source davon. Mein Programm generiert nur die Daten und schreibt sie weg.

    Laut HexEditor sehen die Daten am Ende korrekt aus und bestimmte wichtige Zwischensequenzen sind auch vorhanden und an der richtigen Stelle, gehe also mal davon aus, dass die Datei ok ist, werde das aber noch näher überprüfen.

    Danke für den Hinweis.



  • Compiliert mit BCB4, geteste auf völlig leerer NTFS-Partition:
    API; number of blocks = 1000; block size = 1M
    time = 32.7581s; tp = 32.0097MB/s
    API; number of blocks = 10000; block size = 128k
    time = 26.8433s; tp = 48.8286MB/s
    API WT; number of blocks = 1000; block size = 1M
    time = 29.4683s; tp = 35.5832MB/s
    API WT; number of blocks = 10000; block size = 128k
    time = 26.4855s; tp = 49.4881MB/s
    STL; number of blocks = 1000; block size = 1M
    time = 33.0335s; tp = 31.7428MB/s
    STL; number of blocks = 10000; block size = 128k
    time = 26.7339s; tp = 49.0284MB/s

    Die Blockgrösse scheint wohl wichtiger als alles andere zu sein. Dass WT kaum Gewinn bringt überrascht mich stark.


  • Mod

    Dieser Test Code ist nicht gut und sagt nichts.

    1. Er benutzt immer die selbe Datei.
    2. Der zweite Schreibzyklus erfolgt bereits in eine allokierten Bereich.
    3. Für was sind die seeks bei jedem Zyklus. Das ist unnötig.

    Habe den Code verändert.
    Ganz klar zu sehen: STL ist die lahme Ente!
    Die CRT baut auch einen Buffer ntern auf, deswegen bringen große Blöcke gar nichts.
    API mit write through und 1MB Blöcken ist der Spitzenreiter.

    Man merkt, dass zu große Blöcke nichts bringen! Außer man verwendet Write through.

    Alle Zeiten sind aus dem Debug Build:
    API number of blocks 1000 block size = 1024KB
    time = 40.4724s; tp = 25.9084MB/s
    API number of blocks 4000 block size = 256KB
    time = 33.9254s; tp = 30.9083MB/s
    API number of blocks 8000 block size = 128KB
    time = 36.0559s; tp = 29.082MB/s
    API WT number of blocks 1000 block size = 1024K
    time = 28.5668s; tp = 36.7061MB/s
    API WT number of blocks 4000 block size = 256KB
    time = 38.7442s; tp = 27.0641MB/s
    API WT number of blocks 8000 block size = 128KB
    time = 34.4901s; tp = 30.4023MB/s
    CRT number of blocks 1000 block size = 1024KB
    time = 46.2519s; tp = 22.671MB/s
    CRT number of blocks 4000 block size = 256KB
    time = 42.6777s; tp = 24.5696MB/s
    CRT number of blocks 8000 block size = 128KB
    time = 35.5861s; tp = 29.4659MB/s
    STL number of blocks 1000 block size = 1024KB
    time = 58.6202s; tp = 17.8876MB/s
    STL number of blocks 4000 block size = 256KB
    time = 52.7365s; tp = 19.8833MB/s
    STL number of blocks 8000 block size = 128KB
    time = 55.4942s; tp = 18.8952MB/s

    BTW: Nachfolgenden Code würdeich niemals so schreiben, ich habe nur auf die schnelle den bestehenden Code ergänzt. 🤡

    // WriteSpeed.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    
    #include <iostream> 
    #include <fstream> 
    #include <cassert> 
    #include <vector> 
    using namespace std; 
    #include <windows.h> 
    
    const DWORD dwFileSizeKB = 1000*1024;
    const DWORD adwBlockSizeKB[] = 
    {
    	1024,
    	256,
    	128,
    };
    
    class FileTest 
    { 
    public: 
    	virtual void create(const char *Name) = 0;
    	virtual unsigned write(char *Data, unsigned Count) = 0; 
    	virtual void flush()=0;
    	virtual void close()=0;
    }; 
    
    class FileTestAPI : public FileTest 
    { 
    public: 
    	void create(const char *Name) 
    	{ 
    		//FILE_WRITE_DATA | FILE_READ_DATA 
    		File = CreateFileA(Name, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 
    		assert(File != INVALID_HANDLE_VALUE); 
    	} 
    
    	void createWt(const char *Name) 
    	{ 
    		File = CreateFileA(Name, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); 
    		assert(File != INVALID_HANDLE_VALUE); 
    	} 
    
    	void close() 
    	{ 
    		CloseHandle(File); 
    	} 
    
    	void flush() 
    	{ 
    		FlushFileBuffers(File); 
    	} 
    
    	unsigned write(char *Data, unsigned Count) 
    	{ 
    		DWORD CountRet; 
    		BOOL Success = WriteFile(File, Data, Count, &CountRet, NULL); 
    		assert(Success); 
    		return CountRet; 
    	} 
    protected: 
    	HANDLE File; 
    }; 
    
    class FileTestAPI_WT : public FileTestAPI
    { 
    public: 
    	void create(const char *Name) 
    	{ 
    		File = CreateFileA(Name, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); 
    		assert(File != INVALID_HANDLE_VALUE); 
    	} 
    }; 
    
    class FileTestCRT : public FileTest 
    { 
    public: 
    	void create(const char *Name) 
    	{ 
    		pFile = fopen(Name, "wb"); 
    		assert(pFile); 
    	} 
    
    	void close() 
    	{ 
    		fclose(pFile); 
    		pFile = NULL;
    	} 
    
    	void flush() 
    	{ 
    		fflush(pFile); 
    	} 
    
    	unsigned write(char *Data, unsigned Count) 
    	{ 
    		fwrite(Data,Count,sizeof(char),pFile);
    		return Count; 
    	} 
    private: 
    	FILE *pFile; 
    }; 
    
    class FileTestSTL : public FileTest 
    { 
    public: 
    	void create(const char *Name) 
    	{ 
    		File.open(Name, ios::out | ios::in | ios::trunc | ios::binary); 
    		assert(File); 
    	} 
    
    	void close() 
    	{ 
    		File.close(); 
    	} 
    
    	void flush() 
    	{ 
    		File.flush(); 
    	} 
    
    	unsigned write(char *Data, unsigned Count) 
    	{ 
    		File.write(Data, Count); 
    		assert(File.good()); 
    		return Count; 
    	} 
    private: 
    	fstream File; 
    }; 
    
    void write(FileTest &FileTest, unsigned NumBlocks, unsigned BlockSize) 
    { 
    	vector<char> Buffer(BlockSize);
    	for (unsigned i=0; i<BlockSize; ++i)
    		Buffer[i] = (char)i;
    
    	LARGE_INTEGER Freq; 
    	QueryPerformanceFrequency(&Freq); 
    	LARGE_INTEGER StartTime; 
    	QueryPerformanceCounter(&StartTime); 
    
    	for (unsigned Block = 0; Block < NumBlocks; Block++) 
    		FileTest.write(&Buffer[0], BlockSize); 
    	FileTest.flush();
    
    	LARGE_INTEGER StopTime; 
    	QueryPerformanceCounter(&StopTime); 
    	double Time = static_cast<double>(StopTime.QuadPart - StartTime.QuadPart) / Freq.QuadPart; 
    	cout << "time = " << Time << "s; tp = " << NumBlocks * BlockSize / Time / 1e6 << "MB/s" << endl; 
    
    } 
    
    void write(FileTest &FileTest, const char *filename, const char *testname)
    {
    	for (int i=0; i<3; ++i)
    	{
    		DWORD dwBlockSize = adwBlockSizeKB[i];
    		DWORD dwNumBlocks = dwFileSizeKB/dwBlockSize;
    		cout << testname << " number of blocks " << dwNumBlocks << " block size = " << dwBlockSize << "KB" << endl; 
    		FileTest.create(filename);
    		write(FileTest, dwNumBlocks, dwBlockSize*1024); 
    		FileTest.close();
    	}
    }
    
    int main() 
    { 
    	write(FileTestAPI(),"test1.dat","API");
    	write(FileTestAPI_WT(),"test2.dat","API WT");
    	write(FileTestCRT(),"test3.dat","CRT");
    	write(FileTestSTL(),"test4.dat","STL");
    }
    


  • Martin Richter schrieb:

    Dieser Test Code ist nicht gut und sagt nichts.
    1. Er benutzt immer die selbe Datei.

    Wenn man die Festplatte zumüllt, werden die Resultate dadurch auch nicht genauer. Eigentlich spielt es keine Rolle, immer in die gleiche Datei zu schreiben.

    Martin Richter schrieb:

    2. Der zweite Schreibzyklus erfolgt bereits in eine allokierten Bereich.

    🙄

    Martin Richter schrieb:

    3. Für was sind die seeks bei jedem Zyklus. Das ist unnötig.

    Soll nur zeigen, dass mit der stl bei 2GB schluss ist.

    API number of blocks 1000 block size = 1024KB
    time = 31.9021s; tp = 32.8685MB/s
    API number of blocks 4000 block size = 256KB
    time = 17.8999s; tp = 58.5799MB/s
    API number of blocks 8000 block size = 128KB
    time = 18.7416s; tp = 55.9492MB/s
    API WT number of blocks 1000 block size = 1024KB
    time = 18.2901s; tp = 57.3302MB/s
    API WT number of blocks 4000 block size = 256KB
    time = 19.3387s; tp = 54.2218MB/s
    API WT number of blocks 8000 block size = 128KB
    time = 20.8967s; tp = 50.1789MB/s
    CRT number of blocks 1000 block size = 1024KB
    time = 30.3426s; tp = 34.5579MB/s
    CRT number of blocks 4000 block size = 256KB
    time = 17.3728s; tp = 60.3575MB/s
    CRT number of blocks 8000 block size = 128KB
    time = 17.6469s; tp = 59.4199MB/s
    STL number of blocks 1000 block size = 1024KB
    time = 19.5674s; tp = 53.588MB/s
    STL number of blocks 4000 block size = 256KB
    time = 19.7635s; tp = 53.0561MB/s
    STL number of blocks 8000 block size = 128KB
    time = 19.9676s; tp = 52.5138MB/s



  • lesam schrieb:

    Eigentlich spielt es keine Rolle, immer in die gleiche Datei zu schreiben.

    Spielt es natürlich...
    Die MFT für dieses zweite schriben ist schon allokiert worden und muss nicht nochmals neu gesucht werden. Somit ist das erste schreiben immer langsamer als ein folgendes in die gleiche Datei.

    Ein "richtiger" Vergleich ist nur möglich mit gleichen Anfangsbedingungen. Diese sind bisher in keinem Testfall vorhanden.

    Gleich heisst für mich:
    - XP-SP2 ohne zusätzliche Software installiert
    - Rechner neu gebootet (aus dem "Off" Zustand)
    - Eigene Festplatte um die Testdaten drauf zu schreiben
    - Die Festplatte muss entweder komplett neu Formatiert worden sein (natürlich vor dem booten) oder immer der korrekte Zustand wieder hergestellt worden sein (also immer das gleiche Image; natürlich auch vor dem Booten)
    - Nach dem booten dann 60 Sekunden warten und dann den Test starten
    - Dann jeweils immer nur *ein* Testfall durchführen

    Die ganzen obigen Schritte dann führ jeden Testfall von Anfang an durchführen.



  • Jochen Kalmbach schrieb:

    Spielt es natürlich...
    Die MFT für dieses zweite schriben ist schon allokiert worden und muss nicht nochmals neu gesucht werden. Somit ist das erste schreiben immer langsamer als ein folgendes in die gleiche Datei.

    Bei einer Festplatte mit genügend kapazität, werden die Daten beim zweiten Durchgang in andere Sektoren geschrieben als beim ersten Durchgang!

    Jochen Kalmbach schrieb:

    Ein "richtiger" Vergleich ist nur möglich mit gleichen Anfangsbedingungen. Diese sind bisher in keinem Testfall vorhanden.

    Da hast du recht. Aber man sieht zumindest, dass man die stl nicht generell als langsam bezeichen kann.


Log in to reply