C#.NET的垃圾收集没有发挥作用? [英] C# .NET Garbage Collection not functioning?

查看:138
本文介绍了C#.NET的垃圾收集没有发挥作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作在Visual Studio 2010中一个比较大的解决方案,它有多个项目,其中之一是一个的XNA Game项目,另外一个是一个ASP.NET MVC 2项目。

使用我面临着同样的问题,这两个项目:在调试模式下启动它们以后,内存使用量不断上升。它们开始在40和100MB存储器使用分别的,但(分别为10和30分钟)既爬升到1.5GB相对较快。之后,它有时会下降回落到接近初始使用,其他时候它只是抛出 OutOfMemoryExceptions

当然,这一切都表明严重的内存泄露,所以这正是我最初试图发现问题。寻找泄漏unsuccesfully后,我打过电话 GC.Collect的()定期(每一次每10秒)。介绍完此黑客,内存使用率维持在45和120MB分别为24小时(直到我停止测试)。

.NET的垃圾回收应该是非常好,但我不禁怀疑它只是没有做它的工作。我已经使用CLR探查,试图解决该问题,并表明,XNA项目似乎由垃圾已经节省了很多,我确实是用字节数组,而是把引用应该已经被删除,因此收集收藏家。

此外,当我打电话 GC.Collect的()定期,内存使用问题似乎已经消失了。有谁知道这可能是造成如此高的内存使用情况?它是否可能与在调试模式下运行?

解决方案
  

在寻找泄漏unsuccesfully

更努力=)

在内存托管语言泄漏可能会非常棘手追查。我曾与展鹏蚂蚁内存分析器的好经验。这不是免费的,但他们给你14天,全功能试用。它有一个很好的用户界面,并显示你在哪里,你的内存分配,以及为什么这些对象被保留在内存中。

亚历克斯说,事件处理程序的内存泄漏在.NET应用程序的一个很常见的来源。试想一下:

 公共静态类SomeStaticClass
{
    公共事件的EventHandler SomeEvent;
}

私有类Foo
{
    公共美孚()
    {
        SomeStaticClass.SomeEvent + = MyHandler的;
    }

    私人无效MyHandler的(对象发件人,EventArgs的){/ *任何* /}
}
 

我用一个静态类使问题那样明显地在这里。比方说,您的应用程序的生命周期中,都创造了许多的对象。每个预订了静态类的 SomeEvent 事件。

对象可能跌出范围在同一时间或其他,但静态类维护通过事件处理程序委托的引用,每一个。因此,他们保持活力无限。在这种情况下,该事件处理程序简单地需要被脱钩

  

...在XNA项目似乎都节省了大量的字节数组我确实用...

您可能会运行到碎片的蕙。如果您分配大对象非常频繁,他们可能会造成问题。这些对象的总规模可能会比分配到运行时的总内存要小很多,但由于碎片有很多分配给您的应用程序使用的内存。

我联系到上面的分析器会告诉你,如果这是一个问题。如果是,你可能会就能下来的地方追踪到的对象泄漏。我只是定格在我的应用程序中的问题显示出相同的行为,这是由于的MemoryStream 不释放其内部的字节[] 即使调用的Dispose()就可以了。包裹流中的哑流归零它解决了这一问题。

此外,说明明显,请务必处置的对象实施的IDisposable 的()。有可能是周围地势本土资源。同样,一个优秀的分析器会赶上这一点。

我的建议;这不是GC,问题是在你的应用程序。使用一个分析器,获得了较高的内存消耗状态,你的应用程序,生成内存快照,并开始分析。

I am working on a relatively large solution in Visual Studio 2010. It has various projects, one of them being an XNA Game-project, and another one being an ASP.NET MVC 2-project.

With both projects I am facing the same issue: After starting them in debug mode, memory usage keeps rising. They start at 40 and 100MB memory usage respectively, but both climb to 1.5GB relatively quickly (10 and 30 minutes respectively). After that it would sometimes drop back down to close to the initial usage, and other times it would just throw OutOfMemoryExceptions.

Of course this would indicate severe memory leaks, so that is where I initially tried to spot the problem. After searching for leaks unsuccesfully, I tried calling GC.Collect() regularly (about once per 10 seconds). After introducing this "hack", memory usage stayed at 45 and 120MB respectively for 24 hours (until I stopped testing).

.NET's garbage collection is supposed to be "very good", but I can't help suspecting that it just doesn't do its job. I have used CLR Profiler in an attempt to troubleshoot the issue, and it showed that the XNA project seemed to have saved a lot of byte arrays I was indeed using, but to which the references should already be deleted, and therefore collected by the garbage collector.

Again, when I call GC.Collect() regularly, the memory usage issues seem to have gone. Does anyone know what could be causing this high memory usage? Is it possibly related to running in Debug mode?

解决方案

After searching for leaks unsuccesfully

Try harder =)

Memory leaks in a managed language can be tricky to track down. I have had good experiences with the Redgate ANTS Memory Profiler. It's not free, but they give you a 14 day, full-featured trial. It has a nice UI and shows you where you memory is allocated and why these objects are being kept in memory.

As Alex says, event handlers are a very common source of memory leaks in a .NET app. Consider this:

public static class SomeStaticClass
{
    public event EventHandler SomeEvent;
}

private class Foo
{
    public Foo()
    {
        SomeStaticClass.SomeEvent += MyHandler;
    }

    private void MyHandler( object sender, EventArgs ) { /* whatever */ }
}

I used a static class to make the problem as obvious as possible here. Let's say that, during the life of your application, many Foo objects are created. Each Foo subscribes to the SomeEvent event of the static class.

The Foo objects may fall out of scope at one time or another, but the static class maintains a reference to each one via the event handler delegate. Thus, they are kept alive indefinitely. In this case, the event handler simply needs to be "unhooked".

...the XNA project seemed to have saved a lot of byte arrays I was indeed using...

You may be running into fragmentation in the LOH. If you are allocating large objects very frequently they may be causing the problem. The total size of these objects may be much smaller than the total memory allocated to the runtime, but due to fragmentation there is a lot of unused memory allocated to your application.

The profiler I linked to above will tell you if this is a problem. If it is, you will likely be able to track it down to an object leak somewhere. I just fixed a problem in my app showing the same behavior and it was due to a MemoryStream not releasing its internal byte[] even after calling Dispose() on it. Wrapping the stream in a dummy stream and nulling it out fixed the problem.

Also, stating the obvious, make sure to Dispose() of your objects that implement IDisposable. There may be native resources lying around. Again, a good profiler will catch this.

My suggestion; it's not the GC, the problem is in your app. Use a profiler, get your app in a high memory consumption state, take a memory snapshot and start analyzing.

这篇关于C#.NET的垃圾收集没有发挥作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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