本文内容是学习CLR.via C#的21章后个人整理,有不足之处欢迎指导。

昨天是1024,coder的节日,我为自己coder之路定下一句准则--保持学习,保持自信,保持谦逊,保持分享,越走越远。

第一部分—基本原理思想

垃圾回收机制是针对托管堆而言。

不同于C的运行时堆,托管堆是内存是连续的,每次分配新内存,NextObjPtr指针只需要加上新分配内存块大小即可。C运行时堆为了维护链表的完整性,每当分配新的内存时,遍历链表,一旦发现足够大的内存块,则拆分块,修改节点中的指针。从托管堆中分配内存的速度,几乎可以与线程栈分配相媲美。

GC机制回收的就是托管堆中的垃圾对象。

第二部分—基本算法思想

GC检查托管堆中是否有不再使用的对象。

那么什么是不再使用的对象?

首先要解释什么是根(root)。每个应用程序都有一组根,每个根都是一个存储位置,其中包含指向引用类型对象的一个指针。该指针要么运用托管堆中的一个对象,要么为null。类型中定义的任何静态字段被认为是一个根,任何方法参数或者局部变量也被认为是一个根。只有引用类型变量,才被认为是根,值类型的变量永远不被认为是根。

GC开始执行时,假设所有对象都是垃圾。

GC沿着线程栈上检查所有的根,如果发现了一个跟引用堆中的对象,则在这个对象的“同步索引字段”上开启一位,也就是将这个bit设置为1,也就是说这个对象被标记了。

GC就是这样,以递归的方式遍历所有可达的对象。可达的对象也就是说有根的对象,就是在标记阶段被标记的,也就是本次不回收的。所以不可达的对象就被回收了。

进入第二阶段--压缩阶段。

实际上此压缩非彼压缩,在这里是指碎片整理,如何整理呢?如果发现晓得内存块,GC忽略它们,如果发现大的,可用的连续内存块,GC把非垃圾对象移动到这里以压缩堆。

包含只想这些对象的指针的变量和CPU寄存器,现在都会变得无效,NextObjPtr也应重新指向托管堆的结尾。

第三部分—终结列表和F-reachable队列

说到终结列表要从某些不仅占用内存的对象说起,比如FileStream,它不仅占用内存资源,也在占用本地资源。

Finalize方法就是用于释放本地资源的方法。

那么这个终结列表用来做什么呢?微软当然不会画蛇添足,请仔细看好下面这段:

既占用内存资源,又占用本地资源的,在GC回收这样对象所占的内存时,仅仅回收内存时不够的,因为一定要调用Finalize方法来释放本地资源啊!强烈不建议在代码中我们手动Finalize,这需要堆Finalize的实现有相当深刻并且全面的理解。那么微软的GC是什么怎么来给我们执行的呢?这就用到了终结列表,为了一定要保证执行Finalize,在最初我们new操作符分配内存地时候,如果该对象的类型中定义了Finalize方法,那么将该对象的一个指针方法到终结列表当中,当此类对象在托管堆中判定为垃圾的时候,GC扫描终结列表,以查找这些对象的指针,该指针会从终结列表中移除,并追加到F-reachable队列。

那么这个队列干嘛的呢?我认为唯一的目的就是复活对象,并调用Finalize方法释放本地资源(如果对象是死的,我们无法调用其方法),调用方法的是一个微软定义好的优先级比较高的一个线程,听说这样做有很多好处。那么为什么放到F-reachable队列中就复活了?f(finalization)终结,reachable可达的。换言之,可将这个队列看做静态字段那样的一个跟。

第四部分—代的思想和原理

GC机制无论何时,都分为三代,0代,1代,2代。

代是什么,微软关于这个做了假设,新对象生存周期比较短,而老对象倾向于活的久一些。所在代越高的对象,存活的越久,所在代越低的对象,越容易被回收。

代就是托管堆中被分配的内存而已,也可以说把托管堆分成三部分吧?

0代初始的预算大小为256kb,当0代中的内存用完时,为新对象分配内存,0代内存不够用时,GC开始回收第一代,未被标记的对象当然回收,已标记的对象则这些对象提高一代,进入1代区域,与此同理,当一代内存已满时,回收1代,此时根对象也就是标记的对象提升至2代。

再次重点说一下三代预算大小分别为256KB,2MB,10MB,预算大小以提升性能为宜,预算越大,垃圾回收频率越低。再次注意的是,性能提升的理论源于开始的假设:新对象生存期较短,老对象倾向于活的久一些。请仔细看下面一段。

如果GC回收后,0代存活下来的对象很少,或者说回收的内存很多。0代预算可能会从256调整为128。代的分配空间减少,意味着回收频繁回收频繁,但GC所做的工作会减少,从而减小进程的工作集,最理想的状态是0代对象都是当做垃圾被回收,这样不必压缩内存,NextObjPtr指向0代起始处。这样来讲,最开始的假设是是成立的。

浅谈你感兴趣的 C# GC 机制底层的更多相关文章

  1. 浅谈你感兴趣的 CLR GC 机制底层

    本文内容是学习CLR.via C#的21章后个人整理,有不足之处欢迎指导. 昨天是1024,coder的节日,我为自己coder之路定下一句准则--保持学习,保持自信,保持谦逊,保持分享,越走越远. ...

  2. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service ...

  3. 浅谈V8引擎中的垃圾回收机制

    最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...

  4. 浅谈JS异步轮询和单线程机制

    单线程特点执行异步操作 js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步 ...

  5. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  6. 浅谈 G1 GC 日志格式

    在 Java9 中,G1 GC 将成为默认的垃圾收集器,G1 垃圾收集器的关键特性之一是能够在不牺牲吞吐量的同时,限制 GC 暂停时间(即可以设置所需的最大停顿时间). 由于 G1 GC 正在逐渐成为 ...

  7. ? 这是个很好的问题。Go 当前的 GC 显然做了一些额外的工作,但它也跟其他的工作并行执行,所以在具有备用 CPU 的系统上,Go 正在作出合理的选择。请看 https://golang.org/issue/17969 结束语(Closing notes) 通过研究 Go 垃圾收集器,我能够理解 Go GC 当前结构的背景以及它如何克服它的弱点。Go发展得非常快。如果你对 Go感兴趣,最好继

    ? 这是个很好的问题.Go 当前的 GC 显然做了一些额外的工作,但它也跟其他的工作并行执行,所以在具有备用 CPU 的系统上,Go 正在作出合理的选择.请看 https://golang.org/i ...

  8. 【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  9. 浅谈Java回收对象的标记和对象的二次标记过程_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的 ...

随机推荐

  1. 怎样记住Integer的最大值(有趣的思维和搞笑的回答)

    前言 今天一个同事问我,数据库里面的某表如果用int做PK,那该表最多可以放多少记录,我说简单啊,就是2^31(正数),跟.NET的Int32.MaxValue一样,约等于20亿(正数)吧.同事说,那 ...

  2. Linux网络编程系列-TCP传输控制

    滑动窗口(sliding window) 滑动窗口是用于流量控制的,发送端根据接收端的处理能力发送数据,不至于造成过多的丢包. 是发送方和接收方间的协调,对方的接收窗口大小就是自己的发送窗口大小. 在 ...

  3. 解决方法of未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序

    在开发的一个报表转换功能涉及到Excel97-2003(.xls)文件的导入.使用oledb来读取excel数据.代码为: public static DataSet LoadDataFromExce ...

  4. String的length()和Array的length

    String是个final修饰的最终类,不能被继承,String中属性都设置为private,方法为public,并不提供set方法,想要获得字符串的长度必须调用length()方法这个长度是确定的, ...

  5. 大叔也说Xamarin~Android篇~Activity之间传递数组

    回到目录 我们在开发应用程序时,不可能只使用一个Layout或者一个Activity,比如你个管理系统,要求用户先登陆然后再使用,这时你至少要有两个activity吧,先登陆一个,然后成功后需要跳到别 ...

  6. ASP.net的文件扩展名

    尽管ASP.NET中采用的是事件响应模式,使程序开发人员和最终用户感觉与WinForm程序非常接近,但是它毕竟还是Web应用程序.而Web应用程序的特点,就是基于浏览器与服务器的请求与响应的执行方式. ...

  7. Atitit cnchar simp best list  汉字简化方案 最简化汉字256个

    Atitit cnchar simp best list  汉字简化方案 最简化汉字256个 1.1. 最简化发音1 1.2. 根据笔画密度,删除了密度高的字..1 1.3. 使用同发音的英文字母等代 ...

  8. js 判断字符串是否包含另外一个字符串

    示例代码: <script type="text/javascript"> var str = "测试一个字符串(ehtrzes)是否包含另外一个字符串&qu ...

  9. WPF入门教程系列一——基础

    一. 前言   最近在学习WPF,学习WPF首先上的是微软的MSDN,然后再搜索了一下网络有关WPF的学习资料.为了温故而知新把学习过程记录下来,以备后查.这篇主要讲WPF的开发基础,介绍了如何使用V ...

  10. 基于PHP实现阿里云开放存储服务

    开放存储服务(OpenStorageService,简称OSS),是阿里云对外提供的海量,安全,低成本,高可靠的云存储服务.用户可以通过简单的API(REST方式的接口),在任何时间.任何地点.任何互 ...