C++ Win32内存映射文件与CRT fopen/fread的性能对比

C++ Win32内存映射文件与CRT fopen/fread的性能对比,c++,performance,winapi,memory-mapped-files,C++,Performance,Winapi,Memory Mapped Files,我需要按顺序读取(扫描)文件并处理其内容。 文件大小可以是非常小(一些KB)到非常大(一些GB)的任何大小 我在Windows 7 64位上使用VC10/VS2010尝试了两种技术: Win32内存映射文件(即CreateFile、CreateFileMapping、MapViewOfFile等) fopen和fread来自CRT 我认为内存映射文件技术可能比CRT函数更快,但一些测试表明,这两种情况下的速度几乎相同 以下的C++语句用于MMF: HANDLE hFile = CreateFil

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

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

  • Win32内存映射文件(即CreateFile、CreateFileMapping、MapViewOfFile等)
  • fopen和fread来自CRT
  • 我认为内存映射文件技术可能比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\u INFO.dwAllocationGranularity

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


    谢谢。

    如果按顺序访问文件,我相信您不会看到太大的差异。由于文件I/O的缓存量很大,因此可能还使用了+预读


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

    ,因为您是按顺序扫描文件,所以我不希望这两种方法的磁盘使用模式有太大的不同

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


    MMF实际上是Windows实现进程间共享内存的方式,而不是加速通用文件I/O的方式。内核中的文件管理器缓存是您真正需要利用的。这两种方法最终都会涉及磁盘I/O,这将是您的瓶颈。我会用一种方法,我的更高层次的功能更喜欢-如果我需要流,我将与文件,如果我需要顺序访问和固定大小的文件,我会考虑内存映射文件。 或者,如果您有一个只在内存上工作的算法,那么mem映射文件可能更容易解决

    我以为那个内存映射文件 这项技术可能比CRT快 功能,但一些测试表明 两者的速度几乎相同 案例

    您可能正在访问文件系统缓存进行测试。除非显式创建文件句柄以绕过文件系统缓存(
    file\u FLAG\u NO\u BUFFERING
    调用
    CreateFile
    ),否则文件系统缓存将启动并将最近访问的文件保留在内存中

    在打开缓冲的情况下读取文件系统缓存中的文件(操作系统必须执行额外的复制)和系统调用开销之间存在一个很小的速度差异。但出于您的目的,您可能应该坚持使用CRT文件函数


    (从通用操作系统的角度)

    为什么MMF会在页面文件中放一些东西?MMF页面由打开的数据文件支持,而不是页面文件。我同意Ben的观点。复制到页面文件似乎不太可能。是的,使用MMF显式避免了页面文件。但请注意“当将大型文件映射到虚拟内存以对其执行I/O操作时,请注意这样一个事实,即您在虚拟内存中烧掉的每个地址都是应用程序无法使用的地址。使用常规文件I/O例程对大型文件执行读/写操作通常效率更高。”