【问题标题】:Performance of Win32 memory mapped files vs. CRT fopen/freadWin32 内存映射文件与 CRT fopen/fread 的性能
【发布时间】:2011-04-28 03:49:46
【问题描述】:

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

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

  1. Win32 内存映射文件(即 CreateFile、CreateFileMapping、MapViewOfFile 等)
  2. fopen 并从 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_INFO.dwAllocationGranularity

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

谢谢。

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      由于您是按顺序扫描文件,因此我不认为这两种方法的磁盘使用模式会有很大不同。

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

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

      【讨论】:

      • 为什么 MMF 会在页面文件中放一些东西? MMF 页面由打开的数据文件支持,而不是页面文件。
      • 我同意本的观点。复制到页面文件似乎不太可能。
      • 是的,页面文件是通过使用 MMF 明确避免的。 blogs.msdn.com/b/khen1234/archive/2006/01/30/519483.aspx 但请注意问题“当将大文件映射到虚拟内存以对其执行 I/O 时,请认识到您在虚拟内存中刻录的每个地址都是您的应用程序无法使用的另一个地址。通常是使用常规文件 I/O 例程对大文件执行读/写操作更有效。"
      【解决方案3】:

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

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

      在打开缓冲的情况下读取文件系统缓存中的文件的速度差异很小,因为操作系统必须执行额外的复制以及系统调用开销。但出于您的目的,您可能应该坚持使用 CRT 文件功能。

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

      【讨论】:

        【解决方案4】:

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

        或者,如果您的算法仅适用于内存,那么内存映射文件可能更容易解决。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-25
          • 2011-10-26
          • 2011-01-16
          • 1970-01-01
          相关资源
          最近更新 更多