查看: 23418|回复: 97378
打印 上一主题 下一主题

试着把.net的GC讲清楚(1)

[复制链接]
凯发k8国际
跳转到指定楼层
楼主
发表于 2019-04-19 02:31:55 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

试着把.net的GC讲清楚(1)


什么是GC?

GC(garbage collection)是对内存管理中回收已经不用的内存的一种机制,我们熟知的java和.net都有自己的GC机制,是内存管理的一部分。

为什么会有GC呢?是因为动态的内存分配和分布操作系统是不管的,得各类语言自己实现,例如c和c++自己需要手动管理分配的内存资源,如果不手动释放,那么会造成已经无用的内存不能被操作系统识别使用,也就是所谓的内存泄漏。

.net的GC都是发生在堆(heap),因为这个动态的内存是在堆上分配的。为什么.net 没有像c++一样提供手动管理内存的操作?因为手工管理内存非常容易出问题,开发人员不应花费时间在这个上面,避免人为问题,就找一个管理内存的“人”来,处理这些事情,于是GC就出现了(说一句话,以前自己是c、c++出身,真的一个语言影响一个人的知识广度和深度),大家都不用考虑这些事情,集中在重要的事情上,就像自己找了个管家,而且是专业的,不会出错的那种,省心。

GC有哪些分类?

我了解到的有:Reference Count、Mark and Sweep(升级版Mark and Compact)、Copy and Collection
现在java和.net 使用的是Mark and Compact算法,这个算法是从Mark and Sweep算法演变过来的,下来就讲讲Mark and Sweep。

Mark and Sweep:分为两个阶段,第一阶段标记所有现在还可以使用的对象,第二阶段清除标记的对象之外的内存。

在.net中,GC管理了一组root(由全局对象组成),通过遍历所有的root机器引用的子对象,进行内存中的存活对象的标记,之后就清除未标记为存活的对象。这就是Mark and Sweep算法,但是这个造成了一个问题,就是回收后的内存是成了筛子了,这个时候如果来一个大的对象需要分配内存,那么空余内存总额大于分配对象的大小,但是找不到一个连续的可以容下这个对象大小的内存,这个时候怎么办?其实模拟操作系统,再做一个内存管理的机制就行,在逻辑上看着连续就行了。当然这个不是本次讨论的对象,Mark and Compact解决了内存不连续的问题,因为它把内存做了一次整理(把不相邻的内存移动到一块,看着就连续了)

Mark and Compact:在Mark and Sweep基础上做了一次内存整理,因为内存做整理的时候,对象的引用是不能被使用的,引用地址会变,所以啊,GC的时候,使用到这些对象的线程什么的是会被挂起等待的,也不能经常回收内存,不然性能堪忧,就是因为回收导致挂起了。

啥是0代、1代、2代对象?

要解释这个问题,还得从内存回收时间说起,这里有个假设(其实也是规则)回收一个内存中所有对的时间大于内存中部分对象的时间,于是就把内存中对象分成了几代,0代对象指最新分配内存的对象,一次类推。其实多少代,这个由GC决定,.net中GC中代数是3代(这个值暂时不能确定能不能改)。

GC怎么管理代对象呢?一般情况下,分配的对象都是0代对象,在分配对象内存时,如果0代对象的内存已经不能容纳新对象了(超过0代对象内存的上限),在gc回收一次0代后,这个还存活的对象代数加1(GC.Collect();GC.GetGeneration(obj)代码验证过,现在不清楚自动触发是不是回收一次加1),同理如果1代对象超过了1代内存的上限,也会触发gc回收1代对象。那么这个内存回收是定是这样的么?不一定,毕竟微软提供了手动触发gc的功能,就是GC.Collect(),有兴趣可以翻翻这个方法。

代数的大小,查了很多资料之后,只发现一篇文章说到,.net中0代和1代之和为16MB,2代内存上限非常的大,具体有framework版本和其他一些因素决定的。

//验证回收一次,对象就升一代
Object obj=new Object();
Console.WriteLine(GC.GetGeneration(obj));
GC.Collect();
Console.WriteLine(GC.GetGeneration(obj));
GC.Collect();
Console.WriteLine(GC.GetGeneration(obj));

Finalize、Dispose是啥?如何理解?

.net中有托管资源和非托管资源的分类,托管资源.net自己就可以管理,非托管资源,需要特殊的方法,也就是托管资源在GC的时候,.net可以自己识别,但是非托管资源,GC是自动释放不了的。

什么是非托管资源?这让我想起之前用mfc写windows程序的时候,什么画刷、画笔、com之类的,就是非托管资源,还有数据库连接、文件、套接字之类的也是,哦,还有流之类的都是。

这些非托管资源,一般都需要自己释放资源,.net提供了IDsiposable的接口,实现这个接口的方法,在里面进行资源释放,使用using语句来简化这个非托管资源的释放工作。

Finalize:这个也能用来释放非托管资源,与IDsiposable接口区别是,它的调用时机是不定的,因为它是由GC调用的,GC调用真的不定的,因为调用一次GC调用会降低程序性能(前面说的,内存压缩导致引用需要变化,而因为线程挂起),下面来说说为什么它是由GC调用的。

在创建对象的时候,会把还有析构函数(编译之后,就是Finalize方法,与c++中的析构函数不同)的对象引用存到一个叫做Finalizer Queue的list中,在GC的时候,如果一个对象是无用的,而且在Finalizer Queue里面有引用,此次并不回收,并且会把引用从Finalizer Queue移到Freachable Queue的list中,Freachable Queue的list有内容之后会启动一个线程,然后执行里面的引用的对象的析构函数,执行完毕后把对象的引用删除,等待下次GC的时候,才进行回收此对象。

所以Finalize的特点就是:

  • 啥时候调用不定
  • 这类对象,需要至少两次GC才能回收。

为什么至少两次,而不是两次,因为.net为我们提供了一个把对象引用放回Finalizer Queue的方法,GC.ReRegisterForFinalize(),如果在Finalize中调用了这个代码,那么就死不了了。

微软不建议使用Finalize方法,就像其他博客中提到的,我们可以把它留作后手,万一那个非托管资源该释放没有释放,可以在Finalize方法中做为最后的保险(算是避免人为原因)。

我确实释放完了非托管资源,就是不想执行Finalize方法,微软也提供了方法了:GC.SuppressFinalize(this),这个方法执行了之后就把这个对象的引用中Finalizer Queue移除了。

LOH是什么?

LOH(large object heap)是为了大对象而专门设计的一个堆,多大的对象会分配到这个堆里面?超过85000个字节的就会。其实这个loh产生原因大对象移动非常的耗时,还不如不移动,例如,3个对象ABC,AB对象大约占个80个字节,C对象占个10000个字节,假设AB对象被回收,那么在移动阶段,就要把10000个字节,往前移动80字节,还不如不移动性能高。这个85000字节也是一个经验值。

既然loh不能移动,那么肯定不能用Mark and Compact中的移动了(使用什么算法现在还不清楚,猜测是Mark and Sweep,或许是特例),并且在只有2代对象回收的时候才进行回收。

GC模式?

  • workstation mode:用于单处理器的系统中,频繁回收,从而阻止一次长时间的回收对程序的挂起时间。
  • server mode:用于多处理器的系统中,为每个处理器都创建一个GC Heap,该模式特点是,分配内存较大,能不回收就不回收,回收时候耗时太长。

其中有Concurrent GC 工作方式,其中workstation mode和server mode都可以配置,在单处理器上设置为true也不生效,主要用于用户线程在gc时候可以大部分时间和gc线程并发,详细可以参考:https://blogs.msdn.microsoft.com/seteplia/2017/01/05/understanding-different-gc-modes-with-concurrency-visualizer/

啥时候需要手动gc?

资源特别紧张的时候,例如之前面试的一家公司,系统是在azure上,内存什么的特别贵,这个时候手动gc可能其中一种手段了。

最后

其实gc的最耗时还是在算法的选择上,比如Mark and Compact中的把内存合并成连续的,这个才是耗时的,如果内存足够多,根本就不需要考虑移动内存。
或者像我之前提的,再在内存上面做一次内存映射的管理,也可以避免内存不连续的问题,当然肯定会遇到各种各样的问题。

当前文章://unokeji/201970472.html

发布时间:2019-04-19 02:32:15

兴發娱乐首页 星鱼娱乐app下载 真人麻将用微信付款下载 888大奖娱乐城(娱乐平台) ca888亚洲城_ca88亚洲城手机版入口|亚洲城登陆大厅 大红鹰娱乐|官方网站 世爵娱乐_世爵娱乐平台_世爵娱乐平台客户端 网上买彩票网站_网上买彩票哪家好? 优发国际_www.ufa8.com|优发国际网址 

点击获取礼包
澳门十三第手机app下载
沙发
发表于 2019-04-19 04:09:02 | 只看该作者
可惜,大概是放不下面子,也可能过去争一姐而元气大伤的经历,让她有了教训,盛夏并没有出现在他的直播间。
回复 支持 反对

使用道具 举报

大奖游戏官方站
板凳
发表于 2019-04-19 01:05:27 | 只看该作者
他的手一挥,一股强大的异能从他的手中喷涌而出,直接向着孙艺维冲了过去。/unoproduct/s6pq9.html
回复 支持 反对

使用道具 举报

优发国际平台
地板
发表于 2019-04-19 00:02:34 | 只看该作者
“李局这话怎么说的,我只是在履行一个警察的职责而已。”秦江海淡笑着道。
回复 支持 反对

使用道具 举报

龙虎稳赢的公式方法
5#
发表于 2019-04-19 05:50:57 | 只看该作者
叶扬将这艘残破的飞行器收进了绝对空间中,他自己也是闪身进入到了绝对空间里。
回复 支持 反对

使用道具 举报

大红鹰葡京会线路检测
6#
发表于 2019-04-19 06:55:05 | 只看该作者
“家法伺候。”刘皓在柳梦璃耳边说道,柳梦璃顿时俏脸微红,眼眸放佛都能滴出水来了,她当然知道刘皓所谓的家法伺候是什么了。
回复 支持 反对

使用道具 举报

梦之城平台注册
7#
发表于 2019-04-19 06:35:44 | 只看该作者
三人脸色骤变,尤其是玄衣眼神闪过了种种念头,女人本来就比较细心,尤其是她这种高阶炼药师,心如微尘加上大多数女人天生拥有的敏锐直觉,让她察觉到背后有一只无形大手好像在操纵着这一切一般。
回复 支持 反对

使用道具 举报

奇乐国际娱乐
8#
发表于 2019-04-19 04:08:52 | 只看该作者
叶扬并没有停止攻击,那两个人此时则是在急速的闪动着,似乎想要以高速来躲避那魔影的攻击。
回复 支持 反对

使用道具 举报

手机网赌下载客户端
9#
发表于 2019-04-19 00:43:58 | 只看该作者
此时,整个猛虎帮院落彻底被火把点亮,少帮主吴英面色阴沉站在中间,唐牛等人位列两侧。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

新濠天地注册网址是互联网最大的搜索引擎优化研究中心,是致力于培养学员用户体验意识和提供专业技术解答的专业培训机构, 成立于2007年,2008年第一家入驻歪歪的培训机构,2014年成为腾讯课堂战略合作机构。
© 2007-2016 新濠天地注册网址 湘ICP备13004652号-1 Powered by Discuz!X  Template by 新濠天地注册网址 
快速回复 返回顶部 返回列表