分页活动内存到磁盘的速率非常高,但内存使用率却很低

And*_*sen 11 c# memory-management pagefile

正如标题所述,我遇到了高页面文件活动的问题.

我正在开发一个处理大量图像的程序,它从硬盘加载.它从每个图像生成一些数据,我保存在列表中.对于每3600张图像,我将列表保存到硬盘驱动器,其大小约为5到10 MB.它运行速度尽可能快,因此最多可以输出一个CPU线程.

该程序工作,它生成它应该的数据,但是当我在Visual Studio中分析它时,我得到一个警告说:DA0014:极高的分页活动内存到磁盘的速率.

根据任务管理器,该程序的内存消耗约为50 MB,似乎是稳定的.当我运行该程序时,我在4 GB中剩下大约2 GB,所以我想我的内存不足. 我的程序的内存使用情况http://i.stack.imgur.com/TDAB0.png

例如,DA0014规则说明"输出页数/秒通常远大于页面写入数/秒.因为页面输出/秒还包括系统文件缓存中已更改的数据页面.但是,它不是总是很容易确定哪个进程直接负责分页或为什么."

这是否意味着我得到这个警告只是因为我从硬盘驱动器中读取了大量图像,还是其他的东西?不确定我在寻找什么样的错误.

编辑:链接到插入的图像.

EDIT1:图像大小各约为300 KB.在加载下一个之前,我将每个人都给它.

更新:从实验看起来像分页来自加载大量文件.由于我不是C#或底层GDI + API的专家,我不知道哪个答案最正确.我选择了安德拉斯·佐尔坦斯的答案,因为它得到了很好的解释,因为他似乎做了很多工作来向像我这样的新人解释原因:)

And*_*tan 4

更新了以下更多信息

您的应用程序的工作集可能不是很大 - 但虚拟内存大小又如何呢?分页可能因此而发生,而不仅仅是因为其物理尺寸。请参阅在 Windows 8 上运行的 VS2012 Process Explorer的屏幕截图:

VS 2012内存

任务管理器呢?显然,同一进程的私有工作集是 305,376Kb。

我们可以从中得出:a)任务管理器不一定是可信的;b)就操作系统而言,应用程序在内存中的大小比我们想象的要复杂得多。

您可能想看看这个。

分页几乎肯定是因为您对文件所做的操作,而最终数字较高几乎肯定是因为您正在处理的文件数量。对此的一个简单测试是使用不同数量的文件进行实验,并生成最终分页数据的数据集。如果文件数量导致分页,那么您将看到明显的相关性。

然后取出您所做的任何处理(但保留图像加载)并再次比较 - 注意差异。

然后完全删除图像加载代码 - 请注意差异。

显然,当您取消图像加载时,您会发现故障率下降幅度最大。

现在,查看Emgu.CV 图像代码,它在内部使用该类来获取图像位 - 因此通过函数 GdipLoadImageFromFile (该索引的第二个条目Image)启动 GDI+来解码图像(使用系统资源,以及可能的大字节数组) - 然后它将数据复制到包含实际 RGB 值的未压缩字节数组。

该字节数组是使用GCHandle.Alloc(也由GC.AddMemoryPressure和包围)分配的GC.RemoveMemoryPressure以创建固定字节数组来保存图像数据(未压缩)。现在我不是 .Net 内存管理方面的专家,但在我看来,即使每个文件是按顺序加载而不是并行加载,我们这里也有可能产生堆碎片。

我不知道这是否导致硬分页。但似乎有可能。

特别是,图像的内存表示可以专门用于显示,而不是原始文件字节。例如,如果我们谈论 JPEG,则 300Kb JPEG 在物理内存中可能会大得多,具体取决于其大小。例如,1027x768 32 位图像为 3Mb - 并且为每个图像分配了两次,因为它被加载(第一次分配),然后在被处理之前复制(第二次分配)到 EMGU 图像对象中。

但你必须问自己是否有必要找到解决问题的方法。如果您的应用程序没有消耗大量物理 RAM,那么它对其他应用程序的影响就会小得多;如果有足够的物理内存,一个进程多次访问页面文件不会严重影响另一个没有访问页面文件的进程。