Unmanaged memory in a managed program (wrappers for small objects)

  • Thread starter Marek Malowidzki
  • Start date
M

Marek Malowidzki

Hi all,

I am writing a component that exposes a C++ library as a .NET
component. The approach is somewhat automatic: every library C++ class
has its managed C++ counterpart that keeps a pointer to the unmanaged
class instance.

As usually in such a scenario, the IDisposable/Dispose()/Dispose(bool)
pattern should be used. The problem is that in my approach it is often
impractical, as the library's unmanaged objects are quite small and
many of them are created in various places. For example, such a
statement:

O1 o = o2.Prop1.Prop2;

looks quite nice and it is a lot more convenient than:

using (O3 o3 = o2.Prop1) {
using (O1 o = o3.Prop) {

}
}

The problems stems from the fact that lots of small objects are
created. I have found the following 2 approaches to deal with
unmanaged memeory releasing:

1. Do not do anything (wait for GC to collect managed objects and run
finalizers on them, which call delete on internal pointers). Well, I
have performed some stress tests and it seems to work fine - the
memory as displayed by the Windows Task Manager periodically grows and
decreases to the (approximately) the same value.

2. The problem may appear when the unmanaged heap goes out of space
first. So, to address such a situation, I believe that instead of
calling Dipose() on every small object (wrapper), one could do:

using (UnmanagedMemoryManager mm = MyLib.GetMemeoryManager()) {
// do whatever you want, all new objects (wrappers) created
// by the library in this thread will be automatically added
// to the manager and released in Dispose()

O1 o = o2.Prop1.Prop2;
// we want 'o' to stay usable after the using() block finishes;
// tell the manager to not bother about 'o'
mm.DoNotManage(o);

} // call mm.Dispose() and release all objects managed by the
manager,
// which does not include 'o'

return o;

As one can see, the library could have a thread-relative memory
manager and all library objects that require releasing the memory
could be released in "one shot".

What do you think about it?

Best regards,

Marek
 
M

Mattias Sjögren

Marek,

I wouldn't like your second approach if I was a consumer of your
library. One of the prime reasons to use .NET is to *not* have to
worry about memory allocation issues.

I would instead try to do something similar to the handle collector
pattern used internally be the System.Drawing and
System.Windows.Forms. They keep track of how many unmanaged window
handles (or drawing resources) have been created, and after it reaches
a certain threshold they perform a garbage collection. Genghis
(http://www.sellsbrothers.com/tools/genghis/) also has an
implementation of this you can look at.

Either that, or go with option 1 and simply do nothing.

In the future (specifically in the Whidbey release) you'll be able to
tell the garbage collector about the size of unmanaged resorces you
have allocated with a method GC.AddMemoryPressure, so that it's taken
into account.



Mattias
 
M

Marek Malowidzki

Thanks for your input.

Well, I am a bit curious why you think that the "memory manager" is
inconvenient. In fact, you can use it or not, and then you rely on the
default behavior (GC-based collection of both managed and unmanaged
memory). Moreover, if unmanaged new fails, then a dedicated for this
purpose UnmanagedOutOfMemoryException is thrown by the library's code
and a user can manually trigger garbage collection. If this is not
desired, then the manager could be used.

The difference from Gengis is probably that here the allocated objects
are small and, of course, we could still trace their number, but would
it be an interesting info for a library's user?

Marek
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top