Secrets of WPF Memory Allocation

The way WPF manages memory is a bit of a mystery. It all appears to be nicely garbage collected and everything, but I know there are unmanaged resources under there. How does it know when to garbage collect them?

This is especially important for my application, since I have to manage MANY photos on the screen at once. I’m pretty comfortable with the Dispose() idiom – I kind of like knowing where the memory is going when I’m using such large chunks. But with WPF it’s been a mystery.

Enter: .Net Reflector! Not that I would use such a thing. But supposing I did. (Incidentally, I think I owe Lutz Roeder several beers because of this program)

For those that don’t know, there’s a native code library called ‘milcore’ that WPF is built upon. It has a number of handle types. These are wrapped in .NET by subclasses of SafeMILHandle. This is where things become clear – each of these handle wrappers manually puts pressure on the garbage collector according to the estimated size of the object in question. It uses something called MemoryPresssure.Add() to do this.

Which, it turns out, is not actually a way to influence the garbage collector. It’s in PresentationCore.dll: MS.Internal.MemoryPressure. It uses a funny time/size based heuristic to manually call GC.Collect, which we all know and love. So, depending on what you’re doing with MIL Handles and how you’re doing it, WPF will force garbage collection when it feels like it.

Now, I don’t know a whole lot about garbage collectors, but… how can this possibly work? It seems fine in simple cases (allocate a whole ton of memory, null out your references, repeat). But doesn’t it break the useful heuristics that makes gc perform well? For the case of bitmaps especially, it seems that it’s important for GC to know that these are large objects that should be released as soon as possible. More bang for the buck there. (The large object heap comes to mind, but I think that’s to prevent heap fragmentation)

It’s interesting to observe that the base SafeHandle class *does* implement IDisposable. But the MIL handles themselves aren’t publicly accessible, so they can’t be directly used. But an adventurous/insane person might use reflection to pull the MIL Handle out, replace it with null at the source, type it as an IDisposable, and dispose it manually. I may resort to such measures if this memory pressure thing turns out to be as fishy as it smells.

About these ads

3 thoughts on “Secrets of WPF Memory Allocation

  1. It actually all seems to work okay. The only time I’ve run into problems is when allocating a lot of images *really* fast and throwing them away. The solution was to not generate so much garbage. :)

  2. I have a 64 bit app which can’t use more than 1.5GB of managed objects because at this point GC.Collect(2) takes longer than the “funny” 850ms and from this point on my multithreaded application which till this point managed to load work on all 8 core-I7 cores, freezes: One single core is spending 99.7% in GC (and “# induced GC” is incrementing ever 1-2 seconds) and the GUI thread is frozen, too.

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s