终结者队列增长但管理堆没有

The*_*Man 5 xna memory-leaks windbg

我们有某种泄漏,其性质我不明白.Gen0/1/2堆的大小不会增加,但是工作集会增加,直到我们OOM.

DebugDiag告诉我CLR.DLL拥有不断增长的内存,并告诉我我们有一个不断增长的终结器队列 - 数以万计的Texture2D(它是一个XNA应用程序)对象随着时间的推移而增加..但是没有分析器(dotTrace,Ants,CLR) Profiler)可以找到这些对象 - 它们不会显示在堆中,而CLRProfiler声明它们永远不会被分配.

所以我查看WinDbg - 再一次,我可以看到一个不断增长的Finalizer队列,它充满了Texture2D.fReachable是空的,它声称所有这些对象都在堆上.

*0:038> !finalizequeue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 1881 finalizable objects (33e365b0->33e38314)
generation 1 has 41580 finalizable objects (33e0dc00->33e365b0)
generation 2 has 685816 finalizable objects (33b70020->33e0dc00)
Ready for finalization 0 objects (33e38314->33e38314)
      MT    Count    TotalSize Class Name
......snip......
00ce67e0   726827     49424236 Microsoft.Xna.Framework.Graphics.Texture2D*
Run Code Online (Sandbox Code Playgroud)

然后我查找那些726,000个实例,以便找到谁拥有它们.问题是dumpheap说只有218.这就是我所期望的,以及管理的分析者告诉我的内容.

*0:038> !dumpheap -stat -type Microsoft.Xna.Framework.Graphics.Texture2D
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
00ce67e0      218        14824 Microsoft.Xna.Framework.Graphics.Texture2D
Total 218 objects*
Run Code Online (Sandbox Code Playgroud)

那么终结器队列中的其余项目来自哪里?现在我怀疑随着内存分配的增长,内存分配的终结器队列越来越多,因此也就是OOM.由于某种原因,好像这218个项目被多次添加到Finalizer队列中.

非常感谢

安迪

The*_*Man 2

为了完整起见,这就是发生的事情。

XNA 存在一个问题,如果您访问 Device.Texture[] 集合,则会导致在 Texture2D 上调用 ReRegisterForFinalize。Sunburn 每帧都会访问此集合以解决另一个 XNA 问题,因此如果您有大量纹理,那么这可以非常快速地建立。

XNA(Texture3D 等)中有几个地方使用相同的模式,所以我假设您可以通过多种方式重现它。

由于没有 XNA 5 的迹象,我们必须解决它 - 我发现在访问集合后简单地调用 SuppressFINalize 会删除已添加的额外项目。我们认为它是安全的:-) Sunburn 人员正在他们的代码中添加修复程序,我们希望问题能够消失。