For the first time I have looked at the memory usage of a typical Krypton application. I managed to find some low hanging fruit that was ripe for the picking.

Using the commands described in the Find .NET Memory Leaks article I checked the memory usage for the Palette Designer application.

The above picture shows the end of a list showing all the different types present in the application along with how many instances and how much memory they are consuming. As the list is ordered, the ones at the end of the list are consuming the most memory.

Most of the types listed are of no surprise, the PaletteBack, PaletteBorder and PaletteContent types were to be expected. After all, there are many Krypton controls in the palette designer and therefore many state objects. Multiply the number of state instances by the number of properties that need storage and it works out to be a pretty chunky number.

Although I expected a biggish number I was still surprised that they constitute around 200k, 219k and 369k respectively. Given that the vast majority of these instances will only ever contain defaulted values there was definitely room for improvement.

Instead of PaletteBack having a long list of instance fields that are defined with a default value, I created a helper class that contains the actual storage for the background values. This storage is only created when one of the background values is set to be a non default value. This means that if non of the properties is ever altered then the storage instance is never created. In that case we only have a single reference that is defined as null as the entire footprint for the property storage. I applied this technique to the PaletteBorder and PaletteContent types as well.

The big surprise from the investigation was the event handler type that is shown second to last in the above listing. It has 14k instances consuming 465k of memory. All these instances are actually just event handlers used to notify when an object has been changed in a way that requires a repaint. I was amazed there were quite so many being created and therefore taking up so much room.

In retrospect it should have been obvious. Each Krypton control has multiple states and each state has one or more palette objects for storage of appearance values. Each object exposes an event which is fired when a change occurs to the object that would require a repaint. Once you start hooking up all the objects in the palette hierarchy so that all the children are hooked up to notify the parent it leads to the numbers we see.

The solution turns out to be simple but tedious to refactor the code. I have removed all the events that were exposed and instead store just a single delegate that is fired when the repaint is needed. I create a delegate at the top level of the hierarchy and just pass it down the levels so that all the different palettes objects are using the same delegate to perform notifications.

The end result of the changes gives the following listing when running the palette designer a second time.

So the change in footprint are approx…
PaletteBack 200k -> 67k
PaletteBorder 219 -> 66k
PaletteContent 369k -> 85k
EventHandler 465k -> 2k

Although these changes will not make the application any faster they certainly help reduce memory usage which is useful when using a large number of Krypton controls in a single application.

Leave a Reply