2009-11-04 13 views
9

Potrzebuję zapisać dane na dysku. Mam dwie opcje:Co jest szybsze, zapisywanie nieprzetworzonych danych na dysku lub zapisywanie do pliku?

  1. zapisu sektorów surowców (_ write (uchwyt, pBuffer, rozmiar);)
  2. zapisu do pliku (fwrite (pBuffer, wielkość, ilość, pFile);)
.

Która droga jest szybsza?

Spodziewałem się, że funkcja zapisu sektora surowego, _write, będzie bardziej wydajna. Jednak mój wynik testu nie powiódł się! fwrite jest szybszy. _write kosztuje dłuższy czas.

Wkleiłem mój fragment; może mój kod jest błędny. Czy możesz mi pomóc? Tak czy inaczej jest w porządku przez mnie, ale myślę, że surowy zapis jest lepszy, ponieważ wydaje się, że dane z dysku są szyfrowane przynajmniej ....

#define SSD_SECTOR_SIZE 512 
int g_pSddDevHandle = _open("\\\\.\\G:",_O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE); 
TIMER_START(); 
while (ulMovePointer < 1024 * 1024 * 1024) 
{ 
    _write(g_pSddDevHandle,szMemZero,SSD_SECTOR_SIZE); 
    ulMovePointer += SSD_SECTOR_SIZE; 
} 
TIMER_END(); 
TIMER_PRINT(); 
FILE * file = fopen("f:\\test.tmp","a+"); 
TIMER_START(); 
while (ulMovePointer < 1024 * 1024 * 1024) 
{ 
    fwrite(szMemZero,SSD_SECTOR_SIZE,1,file); 
    ulMovePointer += SSD_SECTOR_SIZE; 
} 
TIMER_END(); 
TIMER_PRINT(); 
+4

Pisanie nieprzetworzonych danych wcale nie jest zaszyfrowane - dla użytkownika jest to mylące ... – bdonlan

+3

+1 dla profilowania. (Chociaż to pytanie jest powyżej mojej głowy) – GManNickG

+0

Do bannlan: Po prostu chcę, żeby wyglądało jak zaszyfrowane. Niewidoczne dla użytkowników –

Odpowiedz

6

W przypadku _write() ważna jest wartość SSD_SECTOR_SIZE. W przypadku fwrite rozmiar każdego zapisu będzie faktycznie BUFSIZ. Aby uzyskać lepsze porównanie, upewnij się, że podstawowe rozmiary buforów są takie same.

Jednak jest to prawdopodobnie tylko część różnicy.

W przypadku fwrite mierzysz, jak szybko możesz pobrać dane do pamięci. Nie opróżniono bufora stdio do systemu operacyjnego i nie prosiliśmy systemu operacyjnego o opróżnienie buforów do fizycznej pamięci masowej. Aby porównać bardziej dokładnie, powinieneś zadzwonić fflush() przed zatrzymaniem timerów.

Jeśli naprawdę zależy ci na pobieraniu danych na dysk, a nie tylko na przenoszeniu danych do buforów systemów operacyjnych, powinieneś upewnić się, że wywołasz fsync()/FlushFileBuffers() przed zatrzymaniem stopera.

inne oczywiste różnice:

  • Napędy są różne. Nie wiem jak inaczej.

  • Semantyka zapisu na urządzenie różni się od semantyki zapisów do systemu plików; system plików może opóźniać zapisy, aby poprawić wydajność, aż do wyraźnego odmowy zapisu (np. ze standardowym uchwytem, ​​wywołaniem FlushFileBuffers()); zapisywanie bezpośrednio na urządzeniu niekoniecznie jest zoptymalizowane w ten sposób. Z drugiej strony, system plików musi wykonać dodatkowy I/O do zarządzania metadanymi (przydział bloku, wpisy książki telefonicznej, itp)

Podejrzewam, że widzisz różne polityki, jak szybko rzeczy faktycznie dostać się na dysk.Wydajność dysku twardego może być bardzo szybka, ale potrzebne są duże zapisy, a najlepiej wiele równoczesnych wybitnych operacji. Możesz także uniknąć kopiowania bufora przy użyciu właściwych opcji po otwarciu klamki.

+0

Wynik, aby być fwrite jest 10 razy szybszy niż _write ... SSD_SECTOR_SIZE to 512 –

+0

Jeśli wywołasz fflush() po każdym wywołaniu fwrite, wydajność powinna wyjść Mniej więcej równe. Jednak, jak wspomnieliśmy janm, są tu również inne zmienne, takie jak pamięć podręczna systemu operacyjnego. –

+1

Jeśli naprawdę zależy Ci na wydajności, spróbuję większych zapisów, powiedzmy po 1MB na raz. Lub nawet pojedyncze wywołanie funkcji zapisu, a następnie wywołanie funkcji płukania. Nowoczesne napędy nie zapisują sektorów, piszą ślady. Aby uzyskać dokładne porównanie, należy opróżnić bufory. – janm

18

Prawdopodobnie dlatego, bezpośredni zapis nie jest buforowane. Kiedy dzwonisz pod numer fwrite, robisz buforowane zapisy, które w większości sytuacji wydają się być szybsze. Zasadniczo każdy uchwyt FILE* ma wewnętrzny bufor, który jest przepłukiwany na dysk okresowo, gdy staje się pełny, co oznacza, że ​​kończy się wykonywanie mniejszych wywołań systemowych, ponieważ zapisujesz tylko na dysku w większych porcjach. Innymi słowy, w swojej pierwszej pętli faktycznie piszesz SSD_SECTOR_SIZE bajtów na dysk podczas każdej iteracji. W drugiej pętli nie jesteś. Piszemy tylko bajty SSD_SECTOR_SIZE do bufora pamięci, który, w zależności od rozmiaru bufora, będzie przepłukiwany tylko co n-tą iterację.