内存映射文件的访问模式

编程语言 2026-07-10

我已阅读如下内容:

我找不到以下问题的清晰答案。我的场景是,我有成千上万份大小为25 MB的文件。我需要在这个大型数据库中以频繁的随机访问方式进行极小的读取(四个16位字)。在一个事务内,这些读取保证在同一个文件内,且相距不超过7 kB。事务发生的频率是每毫秒一次。

在大约一个小时内,这些成千上万个文件中,可能被使用的比例大概是多少?

数量很少,大致几十个文件或更少;但我并不知道事先具体是哪些文件。然而,在每个文件内,整个小时里很可能会访问到其中的大部分内容,只是不一定一次性全部访问。

理想情况下,我希望操作系统能自动管理RAM中缓存的内容以及从RAM中清除的内容。我可以设想多种不同的访问模式,但不知道哪一种是正确的:

  • 对于每个文件,在应用程序整个生命周期内,始终保持打开一个覆盖整个文件的 MemoryMappedFile 和一个 MemoryMappedViewAccessor
  • 对于每个文件,在应用程序整个生命周期内,始终保持打开一个 MemoryMappedFile,但在每次事务中打开并关闭一个覆盖整个文件的 MemoryMappedViewAccess
  • 对于每个文件,在应用程序整个生命周期内,始终保持打开一个 MemoryMappedFile,但在每次事务中打开并关闭一个覆盖7 kB范围的 MemoryMappedViewAccessor —— 大概相当于两个操作系统页面
  • 对于每个文件,在应用程序整个生命周期内,始终保持打开一个 MemoryMappedFile,如果读取已经落在正在运行的视图覆盖的7 kB范围内,就保留该视图;否则关闭它并在正确的位置重新打开
  • 忘记一切,直接使用随机访问文件I/O,并希望操作系统的文件缓存工作正常

特别是:如果我把一个 MemoryMappedViewAccessor 打开,是否会强制操作系统把相应的文件内容保存在RAM中?

解决方案

你需要记住以下几点

  • 访问的文件会自动缓存到主内存中。这种缓存无论你是否关闭文件都会存在;若RAM需要,它会被驱逐。
  • 内存映射也差不多,只是把文件的一整段直接映射到虚拟内存页。这些页只有在被访问时才会缓存在物理RAM中,若不需要就会被驱逐。
  • 内存映射的最大好处其实在于直接的虚拟内存映射(而不是 ReadFile 调用)以及跨进程共享。

  • 对于每个文件,在应用程序的整个生命周期内,始终保持打开两个覆盖整个文件的 MemoryMappedFileMemoryMappedViewAccessor*

如果你真的想使用内存映射,那么这会是最有意义的做法。设置成本很高,而且保持大量打开句柄对应用程序也不太友好。

  • 对于每个文件,在应用程序的整个生命周期内,保持打开一个 MemoryMappedFile,但在每次事务中打开并关闭一个覆盖整个文件的 MemoryMappedViewAccess*

这没有意义:你已经知道在事务中需要的数据,何必再创建这么大一个视口?

  • 对于每个文件,在应用程序的整个生命周期内,保持打开一个 MemoryMappedFile,但在每次事务中打开并关闭一个覆盖7 kB范围的 MemoryMappedViewAccessor——大概相当于两个操作系统页面。*

这也没必要,因为设置中的大部分工作量就是视口。

  • 对于每个文件,在应用程序的整个生命周期内,保持打开一个 MemoryMappedFile,如果读取已经落在由正在运行的视图覆盖的7 kB范围内,就保留该视图;否则关闭它并在正确的位置重新打开。*

这是一个小的改进。

  • 忘记一切,直接使用随机访问文件I/O,并希望操作系统的文件缓存工作正常。*

是的,我估计会这样。Windows和其他现代操作系统在缓存文件方面做得相当好,尤其是你很可能只会接触少量文件,而且你大概已经想得太复杂了。

或许最好的改进是把所有文件合并成一个,或者使用一个合适的数据库产品,而不是再造轮子。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章