2008-09-23 20 views
6

Jeśli próbuję określić szybkość odczytu dysku, mogę zakodować procedurę zapisywania plików do systemu plików, a następnie odczytywania tych plików. Niestety nie zapewnia to dokładnej prędkości odczytu, ponieważ system Windows odczytuje pamięć podręczną na dysku.Jak opróżnić/przepłukać system Windows ZOBACZ pamięć podręczną dysku w języku C#?

Czy istnieje sposób na wyczyszczenie pamięci podręcznej dysku na dysku w C#/.Net (lub może przy użyciu wywołań Win32 API), aby można było odczytać pliki bezpośrednio z dysku bez buforowania?

Odpowiedz

4

Dlaczego DIY?

Jeśli potrzebujesz tylko określić szybkość dysku i nie jesteś naprawdę zainteresowany nauką opróżniania buforów wejścia/wyjścia z .NET, możesz po prostu użyć narzędzia DiskSpd z http://research.microsoft.com/barc/Sequential_IO/. Posiada tryby losowe/sekwencyjne z płukania bufora i bez niego.

Strona zawiera również niektóre raporty badawcze związane z I/O, które mogą okazać się przydatne.

0

Znalazłem artykuł this i wygląda na to, że jest to skomplikowany program, ponieważ musisz również spłukiwać inne pamięci podręczne.

12

Constantin: Dzięki! Ten link ma EXE z wiersza poleceń, który wykonuje test, którego szukałem.

ja też znalazłem link wyłączenia tej strony do bardziej ciekawy artykuł (w Word i PDF) na tej stronie: Sequential File Programming Patterns and Performance with .NET

w tym artykule, to mówi o niebuforowanej Występ pliku (IOW, brak odczytu/buforowanie zapisu - tylko surowe wydajność dysku)

podane wprost z artykułu:

nie ma prosty sposób wyłączyć FileStream buforowanie w V2 .NET ram.. Trzeba odwołać się do systemu plików Windows bezpośrednio do uzyskania niebuforowanej uchwyt pliku, a następnie 'wrap' wynik w FileStream jako następuje w C#:

[DllImport("kernel32", SetLastError=true)] 
    static extern unsafe SafeFileHandle CreateFile(
     string FileName,   // file name 
     uint DesiredAccess,  // access mode 
     uint ShareMode,   // share mode 
     IntPtr SecurityAttributes, // Security Attr 
     uint CreationDisposition, // how to create 
     uint FlagsAndAttributes, // file attributes 
     SafeFileHandle hTemplate // template file 
     ); 

    SafeFileHandle handle = CreateFile(FileName, 
          FileAccess.Read, 
          FileShare.None, 
          IntPtr.Zero, 
          FileMode.Open, 
          FILE_FLAG_NO_BUFFERING, 
          null); 

    FileStream stream = new FileStream(handle, 
        FileAccess.Read, 
        true, 
        4096); 

Wywołanie CreateFile() z flagą FILE_FLAG_NO_BUFFERING mówi systemowi plików o obejściu całego oprogramowania pamięci podręcznej dla pliku. „true” wartość przekazana jako trzeci argument do konstruktora FileStream wskazuje, że strumień powinien własność uchwytu pliku, co oznacza, że ​​uchwyt plik zostanie automatycznie zamknięty gdy strumień jest zamknięta. Po tym, hokus-krokus, niepustukowany strumień pliku jest odczytywany i zapisywany w ten sam sposób, jak każdy inny.

+0

Głosowałem za tym, ale to nie zadziałało po testach - niestety do tego momentu było już za późno na usunięcie mojego głosu! Kod nie kompiluje (nie może przekazać 'FileAccess.Read' i podobnego do' CreateFile() 'i jeśli wpiszesz wyliczenia, kod nie działa - nie może przekazać' null' jako hTemplate. – Oliver

+0

@Oliver : Nie patrzyłem na ten kod w (* wygląda na zegarek *) przez 7 lat, więc prawdopodobnie coś się zmieniło. Jestem pewien, że działało 7 lat temu z C#/.NET 2.0 w VS2005 (a może VS2008, nie jestem pewien, czy przełączyłem się jeszcze w tym momencie.) Zobaczę, czy uda mi się znaleźć oryginalny kod, którego używałem, i odesłać go, jeśli go znajdę. – Pretzel

3
const int FILE_FLAG_NO_BUFFERING = 0x20000000; 
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,64 * 1024, 
(FileOptions)FILE_FLAG_NO_BUFFERING | FileOptions.Asynchronous 
& FileOptions.SequentialScan); 
10

Reakcja Fix prawie rację i lepiej niż PInvoke. Ale ma błędy i nie działa ...

Aby otworzyć plik w/o buforowanie trzeba wykonać następujące czynności:

const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000; 

FileStream file = new FileStream(fileName, fileMode, fileAccess, fileShare, blockSize, 
    FileFlagNoBuffering | FileOptions.WriteThrough | fileOptions); 

kilka zasad:

  1. blockSize musi być trudne rozmiar klastra napęd wyrównane (4096 większość czas)
  2. zmiana pozycji pliku musi być zgodna z rozmiarem klastra
  3. nie można odczytać/zapisać mniej n blockSize czy nie blokują dostosowane do jej rozmiar

I nie zapomnij - jest również HDD Cache (które wolniejsze i mniejsze niż OS cache), których nie można wyłączyć przez to (ale czasami FileOptions.WriteThrough pomaga nie zapisywać w pamięci podręcznej). Dzięki tym opcjom nie masz powodu do płukania, ale upewnij się, że właściwie przetestowano, że takie podejście nie spowolni działania, jeśli twoja implementacja pamięci podręcznej będzie wolniejsza.