C#内存映射文件不占用物理内存空间

12

我试图将大量数据缓存在物理内存中,并在本地环境中与其他进程共享。所以我想到了使用MMF,读取了Microsoft MMF文档,看了一些示例并开始调整代码,类似于这样。

MemoryMappedFile MMF = MemoryMappedFile.CreateNew("Features", MaxSize);
.
.
.
using (MemoryMappedViewStream stream = MMF.CreateViewStream())
{
     BinaryWriter write = new BinaryWriter(stream);
     .
     .
     .
     // Fetched the data from database and store it into Rowdata variable.
     while (Rowdata.Read())
     {
          byte[] data = Rowdata.GetFieldValue<byte[]>(0);
          write.Write(data);
     }
}

它不会在内存中保存数据

我正在处理的是IVSSharedMemory,但是内存大小应该比这个要大得多。

enter image description here

创建内存映射文件时是否有什么我忘记做的事?如果有,请告诉我。 在注意到这种意外行为后,我立即在Google上搜索了一下,有些人说这是虚拟内存。但我认为这不是真的,因为文档中在下面的部分解释了这一点。

非持久性内存映射文件

CreateNew和CreateOrOpen方法创建一个未映射到现有磁盘文件的内存映射文件。

先感谢您。确认这是否是MMF的设计目的也将不胜感激。

更新


似乎的确是虚拟内存。就像Mike z所评论的那样,我使用了VMMAP工具检查了我的应用程序正在保留的内存,结果正是我想要看到的。

enter image description here

但是请注意,已提交的内存量已更改。当我的应用程序完全加载所有数据时会发生这种情况。我可以猜测以前的大小只表示我在创建MMF时分配的最大大小。

enter image description here

它是否消失到物理磁盘空间或其他地方了?

我读了很多关于MemoryMappedFile并试图查看底层原理。但我仍然不明白为什么会发生这种情况。真正的数据在哪里?我可以在哪里检查它?


3
我建议使用vmmap这样的工具来查看确切使用了哪些内存,而不是任务管理器,因为后者只能查看私有工作集,据我所知。 - Mike Zboray
1
据我所知,内存映射文件并没有完全加载到内存中。它们是按页(大多数为4k)进行惰性加载的。因此,当您读取MMF时,操作系统将为您处理读取。请查看维基百科以获得更好的解释。也许您的数据被交换到磁盘上,然后从那里读取? - user743414
@user743414 我也这么认为。但当其他进程尝试访问MMF时,我没有在任务管理器中注意到任何磁盘活动。这就是我非常困惑的原因。也许将数据保留在内存中的唯一方法是拥有一个本地变量并将其缓存到其中...谢谢您的评论。 - hina10531
3
如果您已经正确地创建了内存映射文件,它将占用空间。但是,所使用的空间是虚拟的,您无法通过查看进程的工作集(任务管理器)或查找硬盘活动来观察如何使用虚拟内存。虚拟内存的一个重要特点是,在优化您的进程以及计算机上所有进程使用这些资源的方式时,它将实际(有限的)硬件进行虚拟化。尽管答案可能是“否”,但您的问题“我有遗漏什么吗?”无法回答。 - Martin Liversage
@MartinLiversage 我理解虚拟内存的作用。感谢您的确认。 - hina10531
显示剩余2条评论
1个回答

3
内存映射文件是现代操作系统内核提供的一种功能。它的目的不是将文件加载到实际物理内存中,而是利用虚拟内存映射功能,以便访问文件内容,就像它是一个内存块一样。
更准确地说,现代操作系统使用分页机制,使用计算机的MMU芯片将虚拟地址空间映射到物理内存或磁盘上的交换文件中。这就是虚拟内存的实现方式。想法是MMU使用内核维护的映射将CPU的内存访问转换为RAM访问,如果缺页(已经被交换到磁盘或根本没有映射),则产生硬件中断,调用内核解决缓存未命中。对于内存映射文件,此解析采用将缺失的页面加载到主内存中并透明地恢复程序执行的形式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接