GC,Garbage Collect,中辞意思就是垃圾回收,指的是系统中的内存的分配和回收打点。其对系统性能的影响是不成小觑的。今天就来说一下关于GC优化的对象,这里并不着重说观点和理论,主要说一些实用的对象。关于观点和理论这里只做简单说明,具体的大家可以看微软官方文档。
一、什么是GC
GC如其名,就是垃圾收集,固然这里仅就内存而言。Garbage Collector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用措施的root为根本,遍历应用措施在Heap上动态分配的所有东西[2],通过识别它们是否被引用来确定哪些东西是已经死亡的、哪些仍需要被使用。已经不再被应用措施的root或者另外东西所引用的东西就是已经死亡的东西,即所谓的垃圾,需要被回收。这就是GC事情的道理。为了实现这个道理,GC有多种算法。对照常见的算法有Reference Counting,Mark Sweep,Copy Collection等等。目前主流的虚拟系统.NET CLR,Java VM和Rotor都是给与的Mark Sweep算法。(此段内容来自网络)
.NET的GC机制有这样两个问题:
首先,GC并不是能释放所有的资源。它不能自动释放非托管资源。
第二,GC并不是实时性的,这将会造成系统性能上的瓶颈和不确定性。
GC并不是实时性的,这会造成系统性能上的瓶颈和不确定性。所以有了IDisposable接口,IDisposable接口界说了Dispose要领,这个要领用来供措施员显式挪用以释放非托管资源。使用using语句可以简化资源打点。
二、托管资源和非托管资源
托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源。托管资源的回收事情是不需要人工干与干预的,有.NET运行库在合适挪用垃圾回收器进行回收。
非托管资源指的是.NET不知道如何回收的资源,最常见的一类非托管资源是包装操纵系统资源的东西,例如文件,窗口,网络连接,数据库连接,画刷,图标等。这类资源,垃圾回收器在清理的时候会挪用Object.Finalize()要领。默认情况下,要领是空的,对付非托管东西,需要在此要领中编写回收非托管资源的代码,以便垃圾回收器正确回收资源。
在.NET中,Object.Finalize()要领是无法重载的,编译器是按照类的析构函数来自动生成Object.Finalize()要领的,所以对付包罗非托管资源的类,可以将释放非托管资源的代码放在析构函数。
三、关于GC优化的一个例子
正常情况下,我们是不需要去管GC这些对象的,然而GC并不是实时性的,所以我们的资源使用完后,GC什么时候回收也是不确定的,,所以会带来一些诸如内存泄漏、内存不敷的情况,好比我们措置惩罚惩罚一个约500M的大文件,用完后GC不会立刻执行清理来释放内存,因为GC不知道我们是否还会使用,所以它就期待,先去措置惩罚惩罚其他的对象,过一段时间后,发明这些对象不再用了,才执行清理,释放内存。
下面,来介绍一下GC顶用到的几个函数:
GC.SuppressFinalize(this); //请求大众语言运行时不要挪用指定东西的终结器。
GC.GetTotalMemory(false); //检索当前认为要分配的字节数。 一个参数,指示此要领是否可以期待较短间隔再返回,以便系统回收垃圾和终结东西。
GC.Collect(); //强制对所有代进行即时垃圾回收。
GC运行机制
写代码前,我们先来说一下GC的运行机制。大家都知道GC是一个后台线程,他会周期性的查找东西,然后挪用Finalize()要领去消耗他,我们担任IDispose接口,挪用Dispose要领,销毁了东西,而GC并不知道。GC依然会挪用Finalize()要领,而在.NET 中Object.Finalize()要领是无法重载的,所以我们可以使用析构函数来阻止反复的释放。我们挪用完Dispose要领后,还有挪用GC.SuppressFinalize(this) 要领来报告GC,不需要在挪用这些东西的Finalize()要领了。
下面,我们新建一个控制台措施,加一个Factory类,让他担任自IDispose接口,代码如下: