.NET中的垃圾回收(下)

原创 2004年01月06日 10:04:00

垃圾回收性能的优化

l         弱引用(WeakReference

l         代(Generations

 

弱引用(WeakReference

       弱引用(WeakReference)是提高性能的一种方式,用于减少托管堆中大对象的压力。

      

       当一个根指向一个对象时,它被称为这个对象的一个强引用并且这个对象不能被回收,因为应用程序能遍历到这个对象。

 

       当一个对象有一个指向它的弱引用(WeakReference)时,基本上是指如果有内存请求并且GC启动时,这个对象可以被回收,当应用程序再次尝试去访问这个对象时,访问将会失败。另一方面,为了能访问一个被弱引用(WeakReference)的对象,应用程序必须获得一个对这个对象的强引用。如果应用程序在垃圾回收器回收这个对象之前获得了它的强引用,GC将不能回收这个对象,因为有这个对象的强引用存在。

 

       托管堆包含两个管理弱引用(WeakReference)的内部数据结构:短弱引用表和长弱引用表。

 

       两种类型的弱引用:

 

l         短弱引用不追踪复苏。

也就是说,一个有短弱引用的对象会被立即收回,而不用等到运行Finalize方法。

l         长弱引用追踪复苏。

也就是说,只有当长弱引用表中的对象的存储空间可收回的时候GC才回收这个对象。如果对象有Finalize方法,是在Finalize方法被调用了之后并且对象不能复活了。

 

       这两个表简单的存放着分配在托管堆中对象的指针。最初,两个表均为空。当你创建一个弱引用(WeakReference)对象时,对象不从托管堆中分配。而是在一个弱引用表中分配一个空的存储位置;短弱引用使用短弱引用表,长弱引用使用长弱引用表。

 

       让我们看一个例子,看看GC运行时会发生些什么。下面的图(图1和图2)显示了GC运行前和运行后所有内部数据结构的状态。

 

1GC运行前

 

2GC运行后

 

以下是GC运行时进行的操作:

 

1.  GC为所有可遍历的对象建一张图。在上面的例子中,图包含对象B,C,E,G

2.  GC扫描短弱引用表。如果表中指针指向的对象不在图中,那么这个指针标识的是一个不可遍历的对象,短弱引用表中的这个位置置为null。在上面的例子中,对象D的位置置为null,因为它不是图的一部分。

3.  GC扫描Finalization队列。如果队列中的指针所指的对象不在图中,那么这个指针标识一个不可遍历的对象,指针从Finalization队列中移到FReachable队列中。这时,对象被认为是可遍历的,所以加到图中。在上面的例子中,对象A,D,F是不包含在图中但看作是可遍历的对象,因为它们属于Finalization队列。进而Finalization队列被清空。

4.  GC扫描长弱引用表。如果表中的指针指的对象不在图中(现在图包括FReachable队列中指针所指的对象),那么指针标识一个不可遍历的对象,所在位置置为null。由于对象CF都包含在图中,都不置null

5.  GC整理(Compact)内存,挤出不可遍历对象留下的空隙。在上面的例子中,对象H是唯一从堆中删除的对象,它所分配的内存被收回。

 

代(Generations

       由于垃圾回收要在停止整个程序的情况下才能完成,它们可能会在程序执行期间进行任意长时间的中断。GC也有可能中断为满足实时系统的需求而要求及时响应的事件。

 

       GC中有一个特征叫代(Generations),就是专门为提高性能而设计的。一个多代的GC是通过对观察用各种语言编写的大部分程序而得到两个事实进行仔细分析而得到的:

 

1.  新创建的对象拥有更短的生命周期。

2.  越老的对象,存活的越久。

 

多代的回收器通过对象的年龄把它分成若干组,并且年轻的对象比年老的对象回收的更频繁。初始化时,托管堆不含任何对象。所有新的对象都被添加到第0代堆中,直到堆装满了并触发垃圾回收。由于大部分对象存活的时间很短,只有一小部分年轻的对象在第一次回收时存活下来。一旦一个对象在第一次回收后存活下来后,它就被提升到第1代。在垃圾回收后可以说新的对象都在第0代堆中。只有当第0代的堆装满时垃圾回收才会再次被触发。所有第0代存活下来的对象被整理提升到第1代中。然后第0代不含任何对象了,但是所有新的对象都进入了第0代。

 

因此,作为当前代中“成熟”(存活于多代回收器)的对象,它们都会被移到下一级更老的代中。第2代是CLRGC所支持的最大的代。以后回收时,第2代存活的对象将只是简单的停留在第2代。

 

因此,把堆划分成对象的代并且回收和整理更年轻的代中的对象提高了垃圾回收算法的效率,因为从堆中收回了大量的有意义的空间,同时比起回收器检查所有代中的所有对象要快得多。

 

一个能执行多代回收的GC,每次回收都要确保(至少要尽可能)所需时间小于某个最大时间,以帮助为实时环境能做一些配套的实时操作,同时也防止出现让用户明显感觉到的中断现象。

 

垃圾回收相关神话

GC显然比手工内存管理要慢

应解释:不是一定的。现代垃圾回收器看起来运行时和手工存储分配(malloc/freenew/delete)一样快。在一些特殊的程序中,垃圾回收运行的可能不如为用户专门设计的自定义内存分配那么快。但从另一方面说,为了使手工内存管理正确的工作而添加的额外代吗(比如说,显示的引用计数)常常比GC所做的要昂贵的多。

 

GC会使程序中断

对应解释:由于垃圾回收器在查找和回收垃圾对象时通常停止整个应用程序,他们可能会导致中断时间过长而让用户觉察到。但是通过现在优化计数,这些可以感觉到的中断完全可以避免。

 

手工内存管理不会导致中断

对应解释:手工内存管理并不能确保性能。它可能由于大量的分配或释放内存工作而导致中断。

 

使用GC的程序很大并且臃肿;GC不适合小的程序或系统

对应解释:尽管在复杂的系统中使用GC很有优势,也没有理由认为GC在其它尺寸的程序中会引入什么大的开销。

 

我已经听说了GC会使用两次大量的内存

对应解释:对于原来的GC这可能是个事实,但并不是垃圾回收器都是这样的。用于GC的数据结构比那些手工内存管理的要大的多。

 

 

浅谈.NET垃圾回收

最近在做Winform项目优化,项目运行十天,内存就达到3G,真是让人头疼,到现在还没有完全解决,,,下面来说说.NET垃圾回收原理与算法 每个程序都有这样或者那样的资源,如数据库连接、网络连接、...
  • xiaoyiyz
  • xiaoyiyz
  • 2015年01月22日 11:26
  • 888

.NET 分代垃圾回收

.NET框架包含一个托管堆,所有的.NET语言在分配引用类型对象时都要使用它。像值类型这样的轻量级对象始终分配在栈中,但是所有的类实例和数组都被生成在一个内存池中,这个内存池就是托管堆。 .NET框...
  • formiss
  • formiss
  • 2013年01月16日 10:56
  • 1023

深入了解.net垃圾回收机制之代龄与算法详解

一、代龄(Generation)   代龄就是对Heap中的对象按照存在时间长短进行分代,最短的分在第0代,最长的分在第2代,第2代中的对象往往是比较大的。Generation的层级与Fra...
  • superhoy
  • superhoy
  • 2013年01月29日 17:16
  • 937

C#.Net 垃圾回收机制GC详解

C#.Net 垃圾回收机制GC详解,涉及垃圾回收机制的优点、原理、代龄、使用方法等内容。...
  • aoshilang2249
  • aoshilang2249
  • 2014年08月15日 10:10
  • 2800

Asp.Net中的GC(垃圾回收机制)

1.群里讨论中扯出来点,先记录下来关于GC的一些认识 建立一个测试项目。 using System; using System.Collections.Generic;...
  • itmaxin
  • itmaxin
  • 2015年01月16日 15:14
  • 1654

Java与C#的垃圾回收机制

(一)垃圾回收器的基本假定 (1)最近被分配内存空间的对象最有可能需要被释放。在方法被执行前,通常需要为该方法所使用到的对象分配内存空间,搜索最近被分配的对象集合有助于花费最少的工作来释放进可能多的...
  • u011617875
  • u011617875
  • 2014年02月06日 18:08
  • 806

python,.Net,Java的垃圾回收机制

华电北风吹 天津大学计算机学院 日期:2016-08-26一、python的垃圾回收机制 1、引用计数 当一个对象的引用被创建或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引...
  • zhangzhengyi03539
  • zhangzhengyi03539
  • 2016年08月26日 16:39
  • 448

深入理解.NET的垃圾回收(GC)机制

文章来源:http://www.5fire.com/rjkf/6451.htm
  • libaineu2004
  • libaineu2004
  • 2014年10月13日 22:47
  • 4223

.Net 垃圾回收和大对象处理

英文原文:Maoni Stephens,编译:赵玉开(@玉开Sir) 原文地址:http://blog.jobbole.com/31459/ CLR垃圾回收器根据所占空间大小划分对象。大对象和小对象的...
  • xunzaosiyecao
  • xunzaosiyecao
  • 2015年03月15日 21:28
  • 1144

垃圾回收GC:.Net自动内存管理 上(三)终结器

GC提供了另外一个能够给你带来好处的功能:终结器。在一个资源被回收后,终结器允许一个优雅的清理操作。使用终结器,当GC释放资源所占的内存时,它们可以进行适当的自我清理。表面上,终结器看起来直接了当:你...
  • lihui_830501
  • lihui_830501
  • 2014年07月08日 00:40
  • 1774
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET中的垃圾回收(下)
举报原因:
原因补充:

(最多只允许输入30个字)