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

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

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

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

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

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

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

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

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

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

更新了以下更多信息

您的应用程序的工作集可能不是很大 – 但虚拟内存大小呢? 因此可能会发生分页,而不仅仅是因为它的物理大小。 请参阅从Windows 8上运行的VS2012的Process Explorer中截取的屏幕截图:

VS 2012记忆

还有任务经理? 显然,同一过程的私人工作集是305,376Kb。

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

你可能想看看这个。

分页几乎可以肯定是因为你对文件做了什么,而且最终数字很高,因为你正在处理的文件数量很多。 一个简单的测试就是试验不同数量的文件,并生成最终分页数据的数据集。 如果文件数导致分页,那么您将看到明确的相关性。

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

然后完全删除图像加载代码 – 注意区别。

很明显,当您取出图像时,您会看到最大的故障。

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

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

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

特别地,图像的存储器内表示可以特别地围绕显示而不是原始文件字节。 因此,如果我们正在谈论JPEG,那么300Kb JPEG在物理内存中可能要大得多,具体取决于它的大小。 例如,1027×768 32位图像是3Mb – 并且已经为每个图像分配了两次 ,因为它被加载(第一次分配)然后在被处置之前被复制(第二次分配)到EMGU图像对象中。

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

但是,确定哪个进程直接负责分页或为什么并不总是容易的。

魔鬼在那个警察的注意事项中。 位图使用内存映射文件从包含像素数据的文件映射到内存中。 这是避免将数据直接读入RAM或从RAM中读取数据的有效方法,您只需支付使用的费用。 使文件与RAM保持同步的机制是分页。 因此,如果您处理大量图像是不可避免的,那么您将看到很多页面错误。 你使用的工具不够聪明,不知道这是设计的。

function,而不是错误。