加载.NET内存问题〜40张图片,内存不会被收回,这可能是由于LOH碎片 [英] .NET Memory issues loading ~40 images, memory not reclaimed, potentially due to LOH fragmentation

查看:703
本文介绍了加载.NET内存问题〜40张图片,内存不会被收回,这可能是由于LOH碎片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好了,这是我第一次涉足内存配置的是.NET应用程序(CPU调我做了),我打了一下墙上的在这里。

Well, this is my first foray into memory profiling a .NET app (CPU tuning I have done) and I am hitting a bit of a wall here.

我在我的应用程序的视图加载每页40幅影像(最大),每个运行一下〜3MB。页面的最大数量为10看到,因为我不希望保留400的图像或1.2GB内存一次,我设定每个图像为空时,该页面被更改。

I have a view in my app which loads 40 images (max) per page, each running about ~3MB. The max number of pages is 10. Seeing as I don't want to keep 400 images or 1.2GB in memory at once, I set each image to null when the page is changed.

现在,起初我还以为我必须只是陈旧引用这些图像。我下载蚂蚁分析器(伟大的工具BTW),并跑了几个测试。对象生命周期曲线图告诉我,我没有这些图像比在父类中的单一参考其他任何引用(这是由设计,也证实了通过我的code认真梳理):

Now, at first I thought that I must just have stale references to these images. I downloaded ANTS profiler (great tool BTW) and ran a few tests. The object lifetime graph tells me that I don't have any references to these images other than the single reference in the parent class (which is by design, also confirmed by meticulously combing through my code):

父类 SlideViewModelBase 坚持撒手人寰在缓存中,但 MacroImage 属性设置为null时页被改变。我没有看到任何迹象表明这些对象应保持在比预期更长。

The parent class SlideViewModelBase sticks around forever in a cache, but the MacroImage property is set to null when the page is changed. I don't see any indication that these objects should be kept around longer than expected.

我旁边看了看大对象堆和内存使用情况一般。细算三页图像的我对LOH分配的非托管内存和442.3MB 691.9MB。 System.Byte [] ,这是从我的 System.Drawing.Bitmap 的BitmapImage 转换过程pretty的多所有的LOH空间。这里是我的转换code:

I next took a look at the large object heap and memory usage in general. After looking at three pages of images I have 691.9MB of unmanaged memory allocated and 442.3MB on the LOH. System.Byte[], which comes from my System.Drawing.Bitmap to BitmapImage conversion is taking pretty much all of the LOH space. Here is my conversion code:

public static BitmapSource ToBmpSrc( this Bitmap b )
{
    var bi = new BitmapImage();
    var ms = new MemoryStream();
    bi.CacheOption = BitmapCacheOption.OnLoad;
    b.Save( ms,  ImageFormat.Bmp );
    ms.Position = 0;
    bi.BeginInit();
    ms.Seek( 0, SeekOrigin.Begin );
    bi.StreamSource = ms;
    bi.EndInit();
    return bi;
}

我有一个很难找到,所有的非托管内存是怎么回事。我怀疑 System.Drawing.Bitmap 对象在第一,但蚂蚁不显示他们坚持围绕,我也跑了一个测试,我做了绝对的把握,他们都被处置,并没有发挥作用。所以我还没有想通了,所有的非托管内存的来源。

I am having a hard time finding where all of that unmanaged memory is going. I suspected the System.Drawing.Bitmap objects at first, but ANTS doesn't show them sticking around, and I also ran a test where I made absolutely sure that all of them were disposed and it didn't make a difference. So I haven't yet figured out where all of that unmanaged memory is coming from.

我的两个目前的理论是:

My two current theories are:

  1. 蕙碎片。如果我导航离开分页视图,然后单击几个约一半的〜1.5GB的按钮被回收。不过太多了,但有趣的仍然。
  2. 在一些奇怪的WPF约束力的事情。我们确实使用数据绑定来显示这些图片,我的问候,这些WPF如何控制工作的来龙去脉专家。

如果任何人有任何理论或分析提示我将我们在紧张的最后期限,我扰乱了一下,让这最后的部分做,工作非常感激的(当然)。我想,我已经习惯了跟踪内存泄漏的C ++ ......谁的woulda思想?

If anyone has any theories or profiling tips I would be extremely grateful as (of course) we are on a tight deadline and I am scrambling a bit to get this final part done and working. I think I've been spoiled by tracking down memory leaks in C++ ... who woulda' thought?

如果您需要了解更多信息或想我去尝试其他的东西请询问。很抱歉的墙壁在这里-O-文字,我试图把它尽量精简。

If you need more info or would like me to try something else please ask. Sorry about the wall-o-text here, I tried to keep it as concise as possible.

推荐答案

博客文章出现descibe你所看到的,以及所提出的解决方案是创建一个实施流包装另一个流

This blog post appears to descibe what you are seeing, and the proposed solution was to create an implementation of Stream that wraps another stream.

该包装类的Dispose方法需要释放包裹流,以便它可以被垃圾收集。一旦BitmapImage的被初始化与此包装物流,包装流可设置,释放基础流,并允许较大的字节数组本身被释放。

The Dispose method of this wrapper class needs to release the wrapped stream, so that it can be garbage collected. Once the BitmapImage is initialised with this wrapper stream, the wrapper stream can be disposed, releasing the underlying stream, and allowing the large byte array itself to be freed.

在BitmapImage的有一个参考的源流,因此保持MemoryStream的对象还活着。不幸的是,尽管MemoryStream.Dispose已被调用,它不释放字节数组的内存流包装。所以,在这种情况下,位图被参考流,这是参照缓冲器,其可以占用了大量的空间上大对象堆。没有一个真正的内存泄漏;当有位图没有更多的引用,所有这些对象将(最终)被垃圾收集。但由于位图已经做了形象的自己的私有副本(渲染),似乎相当浪费有位图现在已经不必要的正本仍然在内存中。

The BitmapImage keeps a reference to the source stream so it keeps the MemoryStream object alive. Unfortunately, even though MemoryStream.Dispose has been invoked, it doesn't release the byte array that the memory stream wraps. So, in this case, bitmap is referencing stream, which is referencing buffer, which may be taking up a lot of space on the large object heap. There isn't a true memory leak; when there are no more references to bitmap, all these objects will (eventually) be garbage collected. But since bitmap has already made its own private copy of the image (for rendering), it seems rather wasteful to have the now-unnecessary original copy of the bitmap still in memory.

另外,你使用的是什么版本的.NET的?此前.NET 3.5 SP1,有一个已知问题,一个<一个href="http://blogs.msdn.com/b/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx">BitmapImage可能会导致内存泄漏。解决方法是调用冻结上的BitmapImage。

Also, what version of .NET are you using? Prior to .NET 3.5 SP1, there was a known issue where a BitmapImage could cause a memory leak. The workaround was to call Freeze on the BitmapImage.

这篇关于加载.NET内存问题〜40张图片,内存不会被收回,这可能是由于LOH碎片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆