-- 作者:admin
-- 发布时间:11/9/2004 2:26:00 AM
-- Whidbey 中对 GC 的功能两点增强
发信人: flier (小海 [寻找风车中]), 信区: DotNET 标 题: Whidbey 中对 GC 的功能两点增强 发信站: BBS 水木清华站 (Fri Mar 26 09:14:50 2004), 转信 http://61.155.107.18/user8/flier_lu/main.asp?id=1452116 Whidbey 中对 GC 的功能两点增强 Brad Abrams在其blog中发表了一篇介绍Whidbey 中对 GC 的功能增强的文章Teaching an old dog new tricks: GC fun in Whidbey。其中提到两种对Unmanaged Resource的管理的GC增强。Justin Rogers则在其blog中回应前文,提出了一些很有趣的观点The new face of the GC in Whidbey... I'm not sure this is a pretty face...。 新增的GC.AddMemoryPressure函数和GC.RemoveMemoryPressure函数可以提示GC当前Unmanaged资源的使用情况,以便GC判断在合适的时候进行回收工作;以前供WinForm内部使用的HandleCollector类也公开允许用户使用,用于管理Unmanaged资源的自动回收。 对于CLR/JVM这种使用垃圾回收机制的环境,如何处理其无法管理的外部资源类型是一件让人头痛的事情。例如在使用Win32的位图(BITMAP)资源时,在Managed对象中只需保存一个句柄,但实际上内存占用跟位图文件大小相关,同时句柄本身的数量也是受到系统本身限制的。而这些Unmanaged资源对GC来说都是不可见的,GC只能看到这座冰山露出水面的一小部分,其余的部分只能靠程序员自觉管理,如使用Dispose模式。但这样的使用就违背了GC的基本原则,必然会出现两种内存管理模型的冲突。Whidbey中新增的这两个GC的增强,实际上就是分别对这两种内存管理模型, 提供了与GC兼容的接口。 GC.AddMemoryPressure函数和GC.RemoveMemoryPressure函数是全局性统计的函数,它们必须被使用到Unmanaged资源的CLR对象成对地调用,以保障对资源使用情况的精确跟踪。如果一个对象忘记调用RemoveMemoryPressure函数,则此对象和其Unmanaged资源在被施放后,GC认为以前用AddMemoryPressure函数注册的Unmanaged资源仍在使用,会降低GC的准确率。因此最好使用mihailik给出的封装类UnmanagedResource,通过IDispose和Finalizer确保两个函数的匹配调用。 以下为引用: public abstract class UnmanagedResource : IDisposable { readonly int m_PressureAmount; public UnmanagedResource(int pressureAmount) : this( pressureAmount, true ) { } public UnmanagedResource(int pressureAmount, bool addPressureNow) { this.m_PressureAmount=pressureAmount; if( addPressureNow ) ResourceAllocated(); } protected void ResourceAllocated() { GC.AddMemoryPressure(PressureAmount); } protected void ResourceReleased() { GC.RemoveMemoryPressure(PressureAmount); } protected int PressureAmount { get { return m_PressureAmount; } } public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { ResourceReleased(); if( disposing ) { GC.SuppressFinalize(); } } ~UnmanagedResource() { Dispose(false); } } 不过个人认为这种提示的管理粒度过大了,而且过于依赖人的自觉性。不如使用IoC模式的思想,定义一个接口IUnmanagedResource,所有使用Unmanaged资源的类都实现此接口,然后GC提供GC.RegisterForUnmanagedResource函数将对象注册到GC。此接口提供GetUnmanagedResourceSize()函数,让GC了解其Unmanaged资源的使用情况,如 以下为引用: public interface IUnmanagedResource { uint GetUnmanagedResourceSize(); }; class Bitmap : IUnmanagedResource { private long _size; uint GetUnmanagedResourceSize() { return _size; } Bitmap (string path ) { _size = new FileInfo(path).Length; GC.RegisterForUnmanagedResource(this); // other work } } 这样的好处是可以将对Unmanaged资源的管理粒度降低到对象一级,并让CLR对象和Unmanaged资源绑定,确保施放CLR对象时能够同步更新整体资源使用情况的统计数据,代价是GC需要维护一个和Finalizer列表类似的UnmanagedResource列表。 在实现上GC.AddMemoryPressure函数和GC.RemoveMemoryPressure函数更新由GC的一个子类MemoryWatcher维护的几个统计值,并根据一定的策略触发GC的回收条件。 System.Runtime.InteropServices.HandleCollector实现则比较简单,构造函数中指定阈值,自身维护一套计数器,在超出指定范围后回收句柄。使用方法很简单,如下: 以下为引用: // HandleCollector(string name, int initialThreshold, int maximumThreshold); class XXX { static readonly HandleCollector GdiHandleType = new HandleCollector( “GdiHandles”, 10, 50); static IntPtr CreateSolidBrush() { IntPtr temp = CreateSolidBrushImpl(…); GdiHandleType.Add(); return temp; } internal static void DeleteObject(IntPtr handle) { DeleteObjectImpl(handle); GdiHandleType.Remove(); } } 有兴趣的朋友可以进一步看看这个例子: http://www.gotdotnet.com/userfiles/chrisan/HandleCollector.zip -- . 生命的意义在于 /\ ____\ /\_ \ /\_\ http://flier_lu.blogone.net. . . 希望 \ \ \___/_\/\ \ \/_/__ __ _ _★ . . 工作 \ \ ____\\ \ \ /\ \ /'__`\ /\`'_\ . . 爱你的人 \ \ \___/ \ \ \___\ \ \/\ __// \ \ \/ . . 和你爱的人 \ \___\ \ \_____\ \__\ \____\ \ \_\ . . …… \/___/ \/_____/\/__/\/____/ \/_/ @nsfocus.com. ※ 来源:·BBS 水木清华站 smth.org·[FROM: 211.167.254.*] 上一篇 返回上一页 回到目录 回到页首 下一篇
|