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

时间:2012-12-07 08:00:03

标签: c# memory-management pagefile

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

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

该程序有效,它会生成它应该具有的数据,但是当我在Visual Studio中对其进行分析时,我会收到警告:DA0014: Extremely high rates of paging active memory to disk

程序的内存消耗,根据任务管理器大约50 MB并且似乎是稳定的。当我运行程序时,我从4 GB中剩下大约2 GB,所以我想我的内存不足。 Memory usage of my program http://i.stack.imgur.com/TDAB0.png

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

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

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

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

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

2 个答案:

答案 0 :(得分:4)

更新了以下更多信息

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

VS 2012 Memory

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

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

你可能想看看这个。

分页几乎可以肯定是因为您对文件的处理方式以及最终数字很高,因为您正在使用的文件数量很多。对此进行简单测试就是试验不同数量的文件,并生成最终分页数据的数据集。如果文件数导致分页,那么您将看到明确的相关性。

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

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

显然,当您取出图像时,您会看到最大的故障丢失。

现在,查看Emgu.CV Image code,它在内部使用Image类来获取图像位 - 这样就可以通过函数GdipLoadImageFromFile (Second entry on this index)启动GDI +来解码图像(使用系统资源,加上可能的大字节数组) - 然后将数据复制到包含实际RGB值的未压缩字节数组。

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

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

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

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

答案 1 :(得分:1)

  

但是,确定哪个进程直接负责分页或原因并不总是很容易。

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

功能,而不是错误。