内存映射文件的访问模式
我已阅读如下内容:
我找不到以下问题的清晰答案。我的场景是,我有成千上万份大小为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调用)以及跨进程共享。
- 对于每个文件,在应用程序的整个生命周期内,始终保持打开两个覆盖整个文件的
MemoryMappedFile和MemoryMappedViewAccessor*
如果你真的想使用内存映射,那么这会是最有意义的做法。设置成本很高,而且保持大量打开句柄对应用程序也不太友好。
- 对于每个文件,在应用程序的整个生命周期内,保持打开一个
MemoryMappedFile,但在每次事务中打开并关闭一个覆盖整个文件的MemoryMappedViewAccess*
这没有意义:你已经知道在事务中需要的数据,何必再创建这么大一个视口?
- 对于每个文件,在应用程序的整个生命周期内,保持打开一个
MemoryMappedFile,但在每次事务中打开并关闭一个覆盖7 kB范围的MemoryMappedViewAccessor——大概相当于两个操作系统页面。*
这也没必要,因为设置中的大部分工作量就是视口。
- 对于每个文件,在应用程序的整个生命周期内,保持打开一个
MemoryMappedFile,如果读取已经落在由正在运行的视图覆盖的7 kB范围内,就保留该视图;否则关闭它并在正确的位置重新打开。*
这是一个小的改进。
- 忘记一切,直接使用随机访问文件I/O,并希望操作系统的文件缓存工作正常。*
是的,我估计会这样。Windows和其他现代操作系统在缓存文件方面做得相当好,尤其是你很可能只会接触少量文件,而且你大概已经想得太复杂了。
或许最好的改进是把所有文件合并成一个,或者使用一个合适的数据库产品,而不是再造轮子。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。