Page 1 of 1

Microsoft Xna and strings

Posted: Wed Mar 19, 2008 8:44 pm
by mjpchu

Firstly, I'd like to say that this is an excellent program. It's helped me find myriad leaks in a program that we've been working on for several months.

Now, my (first) problem:

We seem to have a big problem with strings leaking, and they all seem to arise from the same type of call. For the sake of brevity, I'll only list the offending piece of code, and try to explain what's going on:

Texture = ResourceManager.LoadTexture(Device, Common.CommonPaths.TexturePath + @"\TrackSymbolSquare.bmp");

Texture is a Windows.Xna.Framework.Graphics.Texture2D variable. The ResourceManager simply ensures that a Texture2D only gets created once, but functionally it returns a new Texture2D. CommonPaths.TexturePath is a static string.

The allocation stack of the new live instance always traces back to the String.Concat() method. My first instinct was that the new immutable string created from the String.Concat() was somehow referencing the static string, but that seems too stupid to be possible.

The only reference to the string is from System.Collections.Generic.Dictionary<ulong, ResourceData> that traces back up to the GraphicsDevice. The GraphicsDevice is a singleton that will never get destroyed until the program exits. The Texture2D instance that would reference that string as its "Name" property does not exist when I take the snapshot.

I don't expect anyone to have knowledge of the inner workings of Microsoft's Xna, but does this seem to be a memory leak in Xna? If more data/info is required to understand this, I'd be happy to provide it, as this problem is really bugging me.

I was going to list this as a separate post, but while looking at the allocation stack, I noticed that the very large number of WeakReference new instances seemed to be arising from the same (or related) calls to Xna methods (e.g. Texture2D.FromFile(), VertexDeclaration..ctor(), etc.).

Posted: Thu Mar 20, 2008 4:28 pm
by Andreas Suurkuusk
I have never looked at XNA before, but I downloaded it and took a quick look. What I could see is that whenever a Texture2D or any other resource is created, it is added to a DeviceResourceManager. This provides a mapping from an unmanaged handle to the managed resource instance and also some caching. The mapping and cached data is stored in a ResourceData struct, which is then stored in a dictionary using a 64-bit unmanaged handle as the key.

When a resource instance is disposed or finalized, it requests the DeviceResourceManager to release all COM references to the native object. However, when DeviceResourceManager has released all COM references, it sets the native COM pointer to zero, BUT as far as I can see, the data is never removed from the dictionary. The cached data will only be overwritten when a new resource has the same handle value as the old resource.

So it seems like there is a memory leak involved when creating and destroying XNA resources. The leak is relatively small, normally only the name of the resource, an empty WeakReference and the ResourceData structure will be leaked. But, if a lot of resources are created and destroyed, this might cause a memory problem.

Whether this memory leak exists when running on the XBox as well I don't know, I have not been able to look at the XBox implementation.

Posted: Thu Mar 20, 2008 5:45 pm
by mjpchu
Looking at my heap snapshot for my program, I was thinking (and hoping) that something like that were the case. I suppose I can dump this problem off on Microsoft. Thanks so much for your help. Incidentally, how did you determine exactly what the DeviceResourceManager does? I'm having a bit of another problem, and it's difficult to determine whether the problem is with Microsoft or our code. Thanks again.


Posted: Fri Mar 21, 2008 7:46 pm
by Andreas Suurkuusk
Reflector is your friend :) . I analysed the XNA assemblies using Lutz Roeder's Reflector. This provided me with information about how textures and other XNA resources are tracked by DeviceResourceManager.