Win32内存映射文件与CRT fopen / fread的性能

时间:2010-10-20 16:17:43

标签: c++ performance winapi memory-mapped-files

我需要按顺序读取(扫描)文件并处理其内容。 文件大小可以是从非常小(某些KB)到非常大(某些GB)的任何内容。

我尝试在Windows 7 64位上使用VC10 / VS2010的两种技术:

  1. Win32内存映射文件(即CreateFile,CreateFileMapping,MapViewOfFile等)
  2. 来自CRT的fopen和fread。
  3. 我认为内存映射文件技术可能比CRT函数更快,但有些测试显示两种情况下的速度几乎相同。

    以下C ++语句用于MMF:

    HANDLE hFile = CreateFile(
        filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN,
        NULL
        );
    
    HANDLE hFileMapping = CreateFileMapping(
        hFile,
        NULL,
        PAGE_READONLY,
        0,
        0,
        NULL
        );
    

    按顺序读取文件,按块查看;每个块的大小为SYSTEM_INFO.dwAllocationGranularity

    考虑到速度与MMF和CRT几乎相同,我使用CRT功能,因为它们更简单,更多平台。但我很好奇:我是否正确使用MMF技术?在这种情况下,扫描文件顺序的MMF性能与CRT文件相同是正常的吗?

    感谢。

4 个答案:

答案 0 :(得分:14)

我相信如果按顺序访问文件,你就不会发现太大的不同。因为文件I / O被高度缓存,所以也可能使用+预读。

如果在文件数据处理过程中有很多“跳转”,情况会有所不同。然后,每次设置新文件指针并读取新文件部分可能会杀死CRT,而MMF将为您提供最大可能的性能

答案 1 :(得分:4)

由于您按顺序扫描文件,我不希望任何一种方法的磁盘使用模式都有很大不同。

对于大型文件,MMF可能会减少数据局部性,甚至会导致页面文件中放置的全部或部分文件的副本,而使用小缓冲区通过CRT进行处理将全部发生在RAM中。在这种情况下,MMF可能会更慢。您可以通过一次仅映射部分基础文件来缓解这种情况,但事情变得更加复杂,而不会有可能战胜直接顺序I / O.

MMF实际上是Windows实现进程间共享内存的方式,而不是加速通用文件I / O的方式。内核中的文件管理器缓存是您真正需要利用的。

答案 2 :(得分:2)

  

我以为内存映射文件   技术可能比CRT更快   功能,但一些测试显示   两者的速度几乎相同   例。

您可能正在为测试命中文件系统缓存。除非您显式创建文件句柄以绕过文件系统缓存(FILE_FLAG_NO_BUFFERING时调用CreateFile),否则文件系统缓存将启动并将最近访问的文件保留在内存中。

在启用缓冲的情况下读取文件系统缓存中的文件之间存在小的速度差异,因为操作系统必须执行额外的复制以及系统调用开销。但就你的目的而言,你应该坚持使用CRT文件函数。

Gustavo Duarte has a great article on memory mapped files(从通用操作系统的角度来看)。

答案 3 :(得分:1)

这两种方法最终都归结为磁盘i / o,这将是你的瓶颈。我会选择一种方法,我的更高级功能更喜欢 - 如果我需要流式传输,我将使用文件,如果我需要顺序访问和固定大小的文件,我会考虑内存映射文件。

或者,如果你的算法只能在内存上运行,那么mem-mapped文件就可以更方便了。