2008-09-23 7 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.

Powiązane problemy