垃圾回收GC:.Net自己主动内存管理 上(二)内存算法


前言


.Net下的GC全然攻克了开发人员跟踪内存使用以及控制释放内存的窘态。然而,你或午想要理解GC是怎么工作的。此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包括很具体的内在算法描写叙述。同一时候。还将讨论GC的内存清理流程及什么时清理,怎么样强制清理。



内存算法



GC检測用于查看堆中是否有对象不再被程序使用。假设这种对象存在,这些对象占用的内存就能够被回收利用。

(假设堆中没有可用内存空间时,new操作符将会抛出OutOfMemoryException异常)GC是如何知道一个对象是否还被程序使用呢?你能够想象一下。这不是一个easy回答的问题。

      

每个程序都有一组根节点(roots)。它们用于识别定位托管堆中的对象或空(null)对象指向的存储空间。比方,程序中全部全局对象指针或静态对象指针都被看作是程序根节点(roots)的一部分。

另外,线程栈中不论什么局部变量或參数对象指针也被看作程序根节点(roots)的一部分。

最后。全部包括托管堆对象指针的CPU寄存器也被看作程序根的一部分。这组激活的根由JIT编译器和CLR维护,并可被GC的算法系统訪问。

      

当GC执行时。它会如果全部堆中的对象都是垃圾。换句话说,它如果程序根节点一開始跟堆中对象没有不论什么联系。如今。GC開始查看程序根节点并为全部与程序根节点有联系的对象创建一个映射图。比方,GC可能会定位指向堆中任一对象的全局变量。

下图描绘出一个带有几个对象的堆,程序根节点直接指向对象A,C,D,F。全部这些对象就会变成映射图的一部分。当加入对象D时,GC会检測到它还指向对象H。因此对象H也被加入到映射图中。GC会一直这样递归全部相关联的对象。


托管堆((对堆与栈疑惑的能够參考:深入浅出图解C#堆与栈))上分配的对象:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVld2hvZWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">



一旦GC完毕这部分映射后,GC就会去检查下一个根节点然后再递归相关联的对象。最后完毕映射。但有一点不同的是,假设GC在递归相关联对象时发现一个对象之前已经映射过了,GC会停到当前节点不再往下延伸。可是其他节点还会继续。

其他节点假设遇到同样情况也会停止,直到全部对象映射完毕。这种映射方式有两个目的。第一。避免反复映射一个或一组对象大大提升了程序性能。第二。它避免了映射死循环。



      
当全部根节点都检查并映射过后,GC映射图里将会包括全部程序根节点可达(直接或间接的訪问)的对象;假设一个对象没有在这个映射图中。说明程序根节点永远不可能訪问到它。那么这个对象就被觉得是垃圾

如今GC能够直线的訪问堆,查找垃圾对象占用的连续性的内存块。然后GC把非垃圾对象占用的内存空间移动到垃圾对象所占用的内存块上(标准的memcpy操作)。并删除全部堆中内存间隙(对象所占用内存块之间的间隙)。当然,这个内存块的移动操作会影响到全部关联的内存指针,由于内存地址发生了变化。因此GC必须改动程序根节点(roots)并确保全部受影响的指针指向对象的新地址。另外。假设不论什么对象包括一个指向其他对象的指针。GC同一时候也会负责纠正这些指针。大家还能够參考我的还有一篇文章:

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第六节 理解垃圾回收GC,提搞程序性能

下图是运行垃圾回收之后的托管堆:


GC回收之后的托管堆:



在全部垃圾对象被回收后。全部非垃圾对象又一次变得紧凑,非垃圾对象指针也会全部被修复。NextObjPtr会被放到最后一个非垃圾对象之后。这时,new操作符又開始偿试创建新对象,程序请求的资源也被成功创建。

你能够看到,GC产生了一次明显的性能消耗,这是使用GC的主要缺点。然而,记住GC仅在堆被占满的情况进行回收,在回收之前。托管堆明显比C语言执行时的堆快非常多。GC还提供了一些优化操作能够大大提高垃圾回收的性能。兴许文章会讨论GC怎么优化垃圾回收的。

有一些非常重要的点要指出来。你不再须要通过写代码去管理程序资源的寿命。文中一開始提到的两种BUG也将不再存在。首先。它不可能再产生资源泄漏,由于不论什么程序根节点(roots)訪问不到的资源(即垃圾)都会被回收。其次,你也不再可能訪问一个被释放掉的资源,由于假设资源可以被訪问到,它就永远不会被释放。假设资源不可以被訪问到。我们也没有理由去訪问它。

以下代码展示了资源是怎么样被分配与管理的:

class Application {
public static int Main(String[] args) { //在堆中创建ArrayList对象,myArray如今作为程序根节点
ArrayList myArray = new ArrayList(); // 在堆中创建10000个对象
for (int x = 0; x < 10000; x++) {
myArray.Add(new Object());
} // 如今,myArray是一个根(在线程栈里)。
// 因此。myArray和10000个对象都是可达的 Console.WriteLine(myArray.Length); // 在代码中myArray最后一个引用(Console.WriteLine(myArray.Length))之后, myArray 不再是一个根
// 不必非要等到此方法返回后,JIT编译器会知道在myArray最后一个引用之后把它标识为非根节点 // 由于myArray不再是根节点,全部10001个对象不再可达
// 它们会被看作是垃圾
// 可是它们会一直存在直到GC对它们进行回收
}
}

假设GC这么出色,为什么C++不使用它呢?原因是GC必须可以识别程序根节点(roots),而且必须可以找到全部对象指针。C++里同意指针进行类型转换,所以不可能确定一个指针指向的是什么。

在一般语言执行时CLR中,托管堆总是可以确定对象的确切类型,并可通过元数据metadata信息决定一个对象的成员指向哪些其他对象。

总结


本文介绍了.NET FRAMEWORK中GC垃圾回收的算法,及简单提及了与C和C++中的不同。

了解内存算法让你知道GC为什么快。GC的什么操作会很消耗性能,从而让你对自己的程序的性能消耗有一个清晰的概念。

下一文中我将继续介绍垃圾回收GC的自己主动内存管理:终节器Finalization。






翻译:http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

垃圾回收GC:.Net自己主动内存管理 上(二)内存算法的更多相关文章

  1. 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配

    垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

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

    垃圾回收GC:.Net自己主动内存管理 上(三)终结器 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主 ...

  3. golang 垃圾回收 gc

    http://ruizeng.net/golang-gc-internals/ 摘要 在实际使用go语言的过程中,碰到了一些看似奇怪的内存占用现象,于是决定对go语言的垃圾回收模型进行一些研究.本文对 ...

  4. 从C#垃圾回收(GC)机制中挖掘性能优化方案

    GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实 ...

  5. Java 垃圾回收(GC) 泛读

    Java 垃圾回收(GC) 泛读 文章地址:https://segmentfault.com/a/1190000008922319 0. 序言 带着问题去看待 垃圾回收(GC) 会比较好,一般来说主要 ...

  6. 类装饰器,元类,垃圾回收GC,内建属性、内建方法,集合,functools模块,常见模块

    '''''''''类装饰器'''class Test(): def __init__(self,func): print('---初始化---') print('func name is %s'%fu ...

  7. 性能测试三十五:jvm垃圾回收-GC

    垃圾回收-GC 三个问题 哪些内存需要回收? 什么时候回收? 如何回收? YoungGC和FullGC: 新生代引发的GC叫YoungGC 老年代引发的GC叫FullGC FullGC会引起整个Jvm ...

  8. 垃圾回收gc --翻译

    原文在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management.基本保持了平译,并在一些地方做了概念解释.(转 ...

  9. 垃圾回收GC

    ​ 每种语言都有自己的垃圾回收机制.接下来我们来讲一下python的垃圾回收机制. 小整数对象池:python对小整数的定义为[-5,257),这些整数对象是提前建立好的,不会被垃圾回收.单个字母也一 ...

随机推荐

  1. Kafka的3节点集群详细启动步骤(Zookeeper是外装)

    首先,声明,kafka集群是搭建在hadoop1.hadoop2和hadoop3机器上. kafka_2.10-0.8.1.1.tgz的1或3节点集群的下载.安装和配置(图文详细教程)绝对干货 如下分 ...

  2. S2深入.NET编程总结

    不知从几何时,我也开始变得懒了,以往为了学习的那股子斗劲也早已不在,是时候反思反思了.失败的检测成绩希望可以把我唤醒. 经过总结,在本书中大概学到了这些知识: 1.如果一个类可序列化,则它的子类和包含 ...

  3. java中的结构--switch选择结构

    if-switch 选择结构 switch结构可以更好的解决等值判断问题switch 选择结构的语法:switch (表达式){ case 常量 1: //代码块1: break; case 常量 2 ...

  4. Android 根据QQ号跳转到QQ聊天界面

    从自己开发的应用中根据QQ号跳转到QQ应用的聊天界面,实现起来很方便: 即: startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(" ...

  5. html5——3D案例(立体汉字,旋转导航)

    1.立体汉字:旋转点left,attr(data-cont)可获取自定义属性值,skewY(倾斜转换)参考地址 2.旋转导航:先移动后旋转,li标签需要延迟执行旋转 注意::hover事件触发自己的: ...

  6. 9-4前端vue面试的问题

    就没有什么顺序了,肖师傅的一些提问: 1- 配置文件中proxyTable的作用 2-@import '~styles/mixins.styl'  ~的作用 3-vue模拟的本地中访问地址的url带有 ...

  7. UICollectionView框架总结

    一.UIcollectionView介绍 1.1.简介 首先看苹果官方文档 UICollectionView Class Reference 的介绍: The UICollectionView cla ...

  8. js 阻止冒泡事件和默认事件

    阻止事件冒泡 window.enent ? window.enent.cancelBubble = true : e.stopPropagation() function stopBubble(eve ...

  9. uva340 Master-Mind Hints (UVA - 340)

    题目简要 题目意思很简单每个测试都由原题目在第一行,然后后面的都是去猜的答案,如果猜测的位置正确那么输出的结果的数对里面的第一个数就加一,如果仅答案正确(原题目里有这个数,但是位置不一样)那么就在输出 ...

  10. 如何反向遍历List集合

    List接口中提供了ListIterator<E> listIterator()这样的一个方法,可以获得一个ListIterator接口的实例,如下: 看一下他的方法: 了解了这些之后再看 ...