The atou program (Program 2-4) illustrates sequential file processing by converting ASCII files to Unicode, doubling the file length. This is an ideal application for memory-mapped files because the most natural way to convert the data is to process it one character at a time without being concerned with file I/O. Appendix C shows that the memory-mapped version can be considerably faster than the file access versions for NTFS files, so the complexity is worthwhile. The book's Web site contains additional performance studies; the highlights are summarized here.
Memory-mapping performance improvements apply only to Windows NT and the NTFS.
Compared with the best sequential file processing techniques, the performance improvements can be 3:1 or greater.
The performance advantage disappears for larger files. In this example, as the input file size approaches about one-third of the physical memory size, normal sequential scanning is preferable. The mapping performance degrades at this point since the input file fills one-third of the memory and the output file, which is twice as long, fills the other two-thirds, forcing parts of the output files to be flushed to disk. Thus, on a 192MB system, mapping performance degenerates for input files longer than 60MB. Most file processing deals with smaller files and can take advantage of file mapping.
/* Chapter 5. Asc2UnMM.c: Memory-mapped implementation. */ #include "EvryThng.h" BOOL Asc2Un (LPCTSTR fIn, LPCTSTR fOut, BOOL bFailIfExists) { HANDLE hIn, hOut, hInMap, hOutMap; LPSTR pIn, pInFile; LPWSTR pOut, pOutFile; DWORD FsLow, dwOut; /* Open and map both the input and output files. */ hIn = CreateFile (fIn, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); hInMap = CreateFileMapping (hIn, NULL, PAGE_READONLY, 0, 0, NULL); pInFile = MapViewOfFile (hInMap, FILE_MAP_READ, 0, 0, 0); dwOut = bFailIfExists ? CREATE_NEW : CREATE_ALWAYS; hOut = CreateFile (fOut, GENERIC_READ | GENERIC_WRITE, 0, NULL, dwOut, FILE_ATTRIBUTE_NORMAL, NULL); FsLow = GetFileSize (hIn, NULL); /* Set the map size. */ hOutMap = CreateFileMapping (hOut, NULL, PAGE_READWRITE, 0, 2 * FsLow, NULL); pOutFile = MapViewOfFile (hOutMap, FILE_MAP_WRITE, 0, 0, (SIZE_T)(2 * FsLow)); /* Convert the mapped file data from ASCII to Unicode. */ pIn = pInFile; pOut = pOutFile; while (pIn < pInFile + FsLow) { *pOut = (WCHAR) *pIn; pIn++; pOut++; } UnmapViewOfFile (pOutFile); UnmapViewOfFile (pInFile); CloseHandle (hOutMap); CloseHandle (hInMap); CloseHandle (hIn); CloseHandle (hOut); return TRUE; }