J.D. Meier's Blog

Software Engineering, Project Management, and Effectiveness

Performance Guideline: Use HandleCollector API when Managing Expensive Unmanaged Resource Handles

Performance Guideline: Use HandleCollector API when Managing Expensive Unmanaged Resource Handles

  • Comments 2

Here's the next .NET Framework 2.0 performance guideline for review from Prashant Bansode, Bhavin Raichura, Girisha Gadikere and Claudio Caldato.

Use HandleCollector API when Managing Expensive Unmanaged Resource Handles

Applies to

  • .NET 2.0

What to Do
Use HandleCollector API when managing expensive Unmanaged Resource Handles from Managed Code using COM Interop.

Why
The HandleCollector API helps to optimize Garbage Collector efficiency while working with expensive unmanaged resource handles. The garbage collector cannot track the Memory allocated by Unmanaged Code, it can lead to un-optimized memory management by garbage collector. The HandleCollector can force garbage collection if the threshold number of handles are reached, thereby improves performance of the application.

When
If it is required to manage multiple Unmanaged Resource Handles in the application, it is recommended to use HandleCollector API to improve GC efficiency by ensuring the objects are destroyed seamlessly on-time.

How
Create an instance of HandleCollector by providing three parameters Handle Name (string), Initial Threshold (int) and Maximum Threshold (int). The initial threshold is the the point at which GC can start performing garbage collection. The maximum threshold is the point at which GC must perform garbage collection.

 ...
 static readonly HandleCollector appGuiHandleCollector = new HandleCollector( “ApplicationGUIHandles”, 5, 30);
 ...

When application creates an expensive handle, application should increase the total handle count by invoking Add method:

 ...
 static IntPtr CreateBrush()
 {
        IntPtr handle = CreateSolidBrush(...);
        appGuiHandleCollector.Add();
       return handle;
 }
 ...

When application destroys an expensive handle, application should decrese the total handle count by invoking Remove method:

 ...
 internal static void DeleteSolidBrush(IntPtr handle)
 {
        DeleteBrush(handle);
        appGuiHandleCollector.Remove();
 }
 ...

Problem Example
A .Net 2.0 Windows Forms based application needs to provide lot of GUI features to facilitate Paint functionality. The code internally uses many unmanaged GUI handles to manage various Bitmaps. If the developer misses out to destroy the handle by calling appropriate Dispose method at appropriate time, the object remains in memory till the time garbage collection is performed. Also, if memory allocation is performed within unmanaged resource, the GC may not be even aware of it to force collection. At runtime, it might be required to force garbage collection to optimize GC memory management for unmanaged allocations.

Solution Example
A .Net 2.0 Windows Forms based application needs to provide lot of GUI features to facilitate Paint functionality. The code internally uses many unmanaged GUI handles to manage various Bitmaps. The application creates an instance of HandleCollector by providing Handle Name, Initial Threshold and Maximum Threshold. When application creates an expensive handle, it increases the total handle count by invoking the Add method. When handle count reaches to the maximum threshold limit, the GC will force garbage collection automatically. Also, if the handle is destroyed, it will automatically reduce the total handle count in the following code:

 ...
 class UnmanagedHandles
 {
       // Create a new HandleCollector
         static readonly HandleCollector appHandleCollector = new HandleCollector("ApplicationUnmanagedHandles", 5, 30);
       public UnmanagedHandles ()
       {
            // Increment Handle Count
             myExpensiveHandleCollector.Add();
       }
       ~ UnmanagedHandles ()
       {
           // Decrement Handle Count
            myExpensiveHandleCollector.Remove();
       }
 }
 ...

Additional Resources

  • These recommendations don't make any sense.

    How is remembering to increment and decrement the handler any easier than remembering to dispose the object?

    What happens if I don't remember to decrement the handler? Does my handler count just keep going up forever?

    Oh wait a second, is all of this suppose to be wrapped in the constructor and destructor? Well your first example certainly doesn't show that.

    Which leads to this question...

    What happens if I need more than [Maximum Threshold] handles? Does it try to do a GC for every additional handle?

    Should the framework developer tell the application developer "Do not EVER make more than X objects of type foo at a time. If you do, performance will grind to a halt. Sorry, the value of X is implementation specific."

    Finally,

    Brush, the example class, doesn't implement this functionality. Do any?

  • Oh, don't forget about the call to Thread.Sleep in the HandleCollector.Add method. That's a nice performance booster.

Page 1 of 1 (2 items)