5

I used the code below to measure the performance difference between reading large, sequential reads of a memory-mapped file, as compared to just calling ReadFile:

HANDLE hFile = CreateFile(_T("D:\\LARGE_ENOUGH_FILE"), FILE_READ_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL); __try { const size_t TO_READ = 32 * 1024 * 1024; char sum = 0; #if TEST_READ_FILE DWORD start = GetTickCount(); char* p = (char*)malloc(TO_READ); DWORD nw; ReadFile(hFile, p, TO_READ, &nw, NULL); #else HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); const char* const p = (const char*)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); DWORD start = GetTickCount(); #endif for (size_t i = 0; i < TO_READ; i++) { sum += p[i]; // Do something kind of trivial... } DWORD end = GetTickCount(); _tprintf(_T("Elapsed: %u"), end - start); } __finally { CloseHandle(hFile); } 

(I just changed the value of TEST_READ_FILE to change the test.)

To my surprise, ReadFile was slower by ~20%! Why?

19
  • Sure you are not just watching the disk cache at work? Commented Mar 10, 2011 at 8:20
  • Not really... how can I be sure? I've turned off the file system cache but I can't do much about the disk cache... Commented Mar 10, 2011 at 8:21
  • reboot. try the test in the opposite order. and many times. Commented Mar 10, 2011 at 8:25
  • @Thilo: There's no "order" to the tests -- notice that only one of them happens at every run, and I alternated the runs. How would rebooting change anything? Commented Mar 10, 2011 at 8:28
  • Rebooting (as in power-cycle) should clear the cache. By order I mean the order in which you run the two test programs. Commented Mar 10, 2011 at 8:31

1 Answer 1

8

FILE_FLAG_NO_BUFFERING cripples ReadFile. The memory-mapped file is free to use whatever read-ahead algorithm it wants, and you've forbidden ReadFile to do the same. You've turned off caching only in the ReadFile version. Memory-mapped files can't work without file cache.

Sign up to request clarification or add additional context in comments.

6 Comments

@Ben: Wait, why wouldn't the memory-mapped file respect the flag?
@Mehrdad: How could it? MapViewOfFile maps pages from the file cache into your process memory space using the MMU.
@Ben: I had no idea how it worked, but I imagined that it caused a page fault whenever a page was accessed, so the kernel could take control and fill the page with the data -- so there didn't actually have to be any caching.
You should also use FILE_FLAG_SEQUENTIAL_SCAN for large sequential reads.
@Mehrdad: It only does that the first time a page is accessed. Re-reading each page 4000 times would be crazy. And it's the cache manager which fills that page with data and decides when to free it... this is how memory-mapped files stay consistent between processes, because the same physical page is mapped by the cache manager into multiple processes. Your process doesn't own the memory.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.