The new face of the GC in Whidbey... I'm not sure this is a pretty face...
Brad Abrams commented several months ago about some changes in the GC that allows you to tune your application for GC collection when working with unmanaged objects. The two concepts he talks about are a small managed object that is hiding a much larger unmanaged object in the back-end. This would allow the memory to hang around based on the smaller size of the managed object without the GC realizing the true size of the object in question. The second concept is that of unmanaged handles and their limited availability. The GC can be tuned to collect more often when the number of allocated handles passes a collection threshhold and it becomes more aggressive as the maximum threshhold is approached. For the complete article check out, http://blogs.msdn.com/brada/archive/2003/12/12/50948.aspx.
Now, I'm a day late and a dollar short to get my questions answered on the original post I'm sure. However, I have some major issues with the patterns discussed in the article as do some of the other people commenting on the new APIs. One individual seems to think that apps could adversely affect the GC by artificially increasing the GC pressure of certain objects. This is definitely a valid concern. Another individual talks about the possibility of balanced calls to Add/Remove when setting pressure. What does happen when you add 5 megs to the pressure pool and then forget to unset it? Does it stick around?
I'm more worried that these methods are general. The GC doesn't know that my object is the one consuming the memory per-say. It simply knows there is an additional 5 megs that is being used and that if it collects it might get that memory back. I've asked the question if a this pointer is being assigned under the scenes on the blog, but I don't think it is. I've also asked that once the object is finalized and removed from the GC, if the pressure will be removed as well in the case I forget my call to RemoveMemoryPressure. While the article shows the call being placed in the Finalizer, I think it is more likely that it will be placed within the Dispose() pattern implementation, since you'd want to relax the GC pressure as soon as the unmanaged memory is released.
Onto the HandleCollector. Is it just me or is this really just a helper library for classes I've already had to write when working with unmanaged resources that have limits. This special handle collector counts the number of times Add/Remove is called and assumes that each one matches the creation and disposal of an unmanaged handle somewhere. I'm assuming that when making calls to Add/Remove decisions are made as to whether or not a collection should occur in order to reclaim some of the unmanaged handles. Note this really only happens if your code is lazy and you don't explicitly Dispose() your managed objects and force the release of the unmanaged handles, so for library programmers this might be a god-send. Then again library programmers have already written their own handle pools to ensure enough handles are available for their systems to run. Unless there is some mystical GC tuning happening behind the scenes, or unless you can attach the type of the object you'd want to collect to this new HandleCollector so that the GC only tries to collect objects that would contain an actual handle, then I don't think this is going to be very useful either.
I'd really love to see some powerful memory management tools being added to my toolbox. Being a developer that lives and breathes plug-in systems, I'm awaiting the day that I can limit the amount of memory consumed by plug-ins in my system or at least spy on them to see which ones are being naughty (within managed code mind you). It'd also be nice to have something like a GC.AvailableForGC(WeakReference) call. That would make that HandleCollector pretty bitchin right. You could loop through all of your object references, figure out only those that are available for GC, then GC.Collect(WeakReference). Talk about some powerful stuff.
Now I know this breaks some of the .NET paradigm of not having to worry about memory, but so does tuning metrics for forcing the GC to collect more often. The more often the GC collects the more of a performance hit your application is going to suffer. I'd rather be in control of collecting just the objects I know are sparsely available, than having to tune my handle collector for 6 hours, trying to find out which values for initial and max threshhold are going to make the GC collect when I need it, but not so much that it affects the performance of my application.