5

We have some sort of a leak, the nature of which I don't understand. Gen0/1/2 heaps do not increase in size however Working Set increases until we OOM.

DebugDiag tells me that CLR.DLL owns the increasing memory and also tells me that we have a growing finalizer queue - 100s of thousands of Texture2D (its an XNA app) objects which increase with time.. However no profiler (dotTrace, Ants, CLR Profiler) can find these objects - they don't show in the heap and CLRProfiler claims they are never allocated.

So I look in WinDbg - once again I can see a growing Finalizer queue full of Texture2D. fReachable is empty and it claims all those objects are on the heap anyway.

*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*

Then I look for those 726,000 instances so that I can find who owns them. Problem is that dumpheap says there's only 218. Thats pretty much what I expect and what the managed profilers tell me exists.

*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*

So where are the rest of the items on the finalizer queue coming from? Right now I suspect the growing finalizer queue for the memory allocations as it grows and therefore out OOM. Its as if those 218 items are being added to the Finalizer queue multiple times for some reason.

Many thanks

Andy

4

2 回答 2

2

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

如果您访问 Device.Texture[] 集合,XNA 存在一个问题,会导致在 Texture2Ds 上调用 ReRegisterForFinalize。Sunburn 在每一帧都访问这个集合来解决另一个 XNA 问题,所以如果你有很多纹理,那么这可以非常迅速地建立起来。

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

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

于 2012-07-25T14:28:51.797 回答
1

是否可以将同一个实例重新添加到 finalize 队列中?来自 Object.Finalize 的文档:

Finalize 仅在给定实例上自动调用一次,除非使用诸如 GC.ReRegisterForFinalize 之类的机制重新注册对象,并且随后未调用 GC.SuppressFinalize。

这是唯一符合您在此处看到的解释的解释。不知道为什么它会重新注册完成。

于 2012-07-21T08:50:42.930 回答