This post is a bit futuristic, but since .NET 2.0 and Visual Studio 2005 release is very near, I thought I should start to talk about it a bit more.

.NET 2.0 will introduce an improved and better GC.
One of the parameters that the GC takes into account is the amount of memory a certain class instance takes. By doing so, the GC can better understand how much memory will be gained by collecting this object.

One of the inputs the GC takes into accoutn when decided whether to initiate a collection or not is the amoutn of managed memory allocated.
If we have a managed class instance that doesn’t allocate a lot of mamanged memory but holds a pointer to a large unmanaged memory (either a reference to a COM object that allocates a lot of information, or directly allocating unmanaged memory using functions such as Marshal.AllocHGlobal) the GC will not know about the unmanaged memory allocated and will not consider scheduling a GC sooner.

This means, that if there is no reference to that object and its finalizer releases the unmanaged memory, until there is a GC and the finalizer thread reaches that object, this unmanaged memory will not be released and may add pressure on the application’s memory usage.

For this purpose, in .NET 2.0 the “AddMemoryPressure” function was added to the GC class.

“AddMemoryPressure” allows the developer to notify the GC about the amount of additional unmanaged memory that was allocated in different places in the application. The GC will take this into account when considering the schedualing of a collection.

For example, if at some point in the application I create a COM object that I know allocates a bit chunk of memory, after creating it I will call “AddMemoryPressure” and give it a rough estimate of the amount of unmanaged memory this COM object takes.

For example:

class MySpecialBitmapClass
{
private long size;

MySpecialBitmapClass(string fileName)
{
size = new FileInfo(fileName).Length;
GC.AddMemoryPressure(size);
}

~MySpecialBitmapClass()
{
GC.RemoveMemoryPressure(size);
}
}

When I create the class I say that I will add a memory pressure which is at least as large as the file I’m working on. When the instance of this class is being finalized it will remove the pressure.

Be sure to tune in to hear some more changes and updates that are coming in .NET 2.0’s GC.

  • Tomer Gabel

    The use of GC.AddMemoryPressure to “compensate” for unmanaged memory is NOT the right way to do things; the GC should not handle unmanaged memory indirectly via finalizers. The very practice of finalizing unmanaged resources is bad (non-deterministic, prone to error, hard to debug), which is why IDisposable was introduced in the first place.

    That aside, you’d want to fix several typoes (accoutn, amoutn, mamanged) and some mangled HTML at the end (which only shows via the RSS feed). Judging by the nature of the mistakes I’d bet that you’re touch-typing on a keyboard you’re not used to, with slower tactile response 🙂

  • Sorry for the late response, I’ve been away on vacation.

    Generally you are right about finalizers being not a very bright way of handling things BUT (and there is a big BUT here) people do forget to use the “using” keywords and people do forget to call dispose.

    Implementing the finalizers is the way for your component to handle these issues. So yes, it might not fit most of the applications but for those of us who write compoenets that we never know how, where and when they will be used finalizers are a MUST.

    Regarding the GC.AddMemoryPressure, again, generally you are correct, BUT in cases when you have a highly mixed application the use inteop heavily, making the GC a bit more aware of the unmanaged memory can boost the performance of the application dramatically. I have seen application in 1.1 that could have greatly benefited from such a feature. Unfortunately it was only available in the newer GC that is being relesed in .NET 2.0.

    The sample I gave was to make the GC aware of unamanged memory allocation and its not indirectly used so that the GC will indirectly handle unmanaged memory.

    Perhaps I should have splitted the post into two sections, one about the features and one about how and when to use them in a manner that will be benefical for everyone (like component writers, high throughput application developers and the rest of the developers).

  • Pingback: A little bit more about GC.AddMemoryPressure » Advanced .NET Debugging()