go语言gc为什么不分代,gc为什么要分代
go语言的垃圾回收有隐患吗
Go的gc没有jvm成熟;
成都创新互联公司专注于柞水企业网站建设,响应式网站开发,成都商城网站开发。柞水网站建设公司,为柞水等地区提供建站服务。全流程按需网站开发,专业设计,全程项目跟踪,成都创新互联公司专业和态度为您提供的服务
Go本身也不会比java产生更多的垃圾(等java有值类型,object在内存能连续分布再说)。
Go 1.5的gc初步做到精确的、并发的,STW gc;
相比jvm的G1缺少:可压缩、可移动、分代式的特性。这些以后都会有。
具体细节google一下,有相关文档。
GC垃圾回收(3)- 三色标记算法
CMS过程在上篇文章 GC垃圾回收(2) 中已经写过。
它分为四个阶段:
其中 并发标记 阶段会有漏标的问题,为解决这个问题,采用了 "三色标记算法"
G1 GC(Garbage First Garbage Collector)是一种服务端应用使用的垃圾收集器,目标是用在 多核、大内存 的机器上,它在大多数情况下可以实现指定的GC暂停时间,同时还能保持较高的吞吐量。它的吞吐量相较PS+PO降低了大概10%~15%,但是大大降低了响应时间,大概200ms的程度
G1内存模型如下:
G1相较之前其它的垃圾回收器,对模型进行了改变,不再进行物理分代,采用逻辑分代。
它不再将连续内存分为Eden区和Old区,而是将内存分为一个个的Region。一块Region(分区)在逻辑上依然分代,分为四种:Eden,Old,Survivor,Humongous(大对象,跨多个连续的Region)。
它的每个分区都可能是年轻代也可能是老年代,但是在同一时刻只能属于某个代。
年轻代、幸存区、老年代这些概念还存在,成为了逻辑上的概念,这样方便复用之前分代框架的逻辑。在物理上不需要连续,这带来了额外的好处——有的分区内垃圾对象特别多,有的分区内垃圾对象很少,G1会优先回收垃圾对象特别多的分区,这样可以花费较少的时间来回收这些分区的垃圾,这也就是G1名字的由来,即首先回收垃圾最多的分区。
新生代其实并不适用于这种算法,依然是在新生代满了的时候,对整个新生代进行回收——整个新生代中的对象,要么被回收、要么晋升,至于新生代也采取分区机制的原因,则是因为这样跟老年代的策略统一,方便调整代的大小。
G1还是一种带压缩的收集器,在回收老年代的分区时,是将存活的对象从一个分区拷贝到另一个可用分区,这个拷贝的过程就实现了局部的压缩。每个分区的大小从1M到32M不等,但都是2的幂次方。
特点:
G1与CMS在并发收集时的算法没太大区别,用的是 三色标记 算法。但ZGC和Shenandoah使用的是 颜色指针 Colored Pointers。
主要用于分代模型中帮助垃圾回收。
为什么需要 card table ?
寻找存活对象并不是一件容易的事。从一个GC root对象寻找,可能被Old区对象引用,这个Old区对象又被Eden区对象引用,那么判断Eden区对象是否存活就需要遍历整个Old区存活对象看是否被Old区对象引用。这样的话每进行一次YGC就要扫描整个Old区。
所以JVM内部,将内存区域分为一个个的card,对象存在一个个的card里。当老年代某个card中的对象指向了年轻代,就会将这个card标记为 Dirty 。这么多card具体哪个是 Dirty的,用位图BitMap来代表(如0110010010,1表示Dirty),这就是Card Table。
Card Table :由于做YGC时,需要扫描整个Old区,效率非常低,所以JVM设计了Card Table, 如果一个Old区Card Table中有对象指向Y区,就将它设为Dirty,下次扫描时,只需要扫描Dirty Card。 在结构上,Card Table用BitMap来实现。
RSet会占用一定的空间,所以ZGC又做了改进,不使用RSet,用颜色指针来标记。
Rset与赋值的效率:
5% ~ 60%(新生代)
G1能跟踪STW停顿时间,根据停顿时间动态调整新生代(Y区)比例
超过单个region的 50% 就是一个大对象,也可跨越多个region。
注意: G1也是存在FGC的,并且一定会被触发。当对象分配不下是会产生FGC。
回收时不分新生代还是老年代什么的,region满了就回收。
MixedGC过程:
跟CMS非常像,MixedGC最后是筛选回收,多了个筛选步骤。筛选就是找出垃圾最多的region。筛选后将存活对象复制到其他region,再将之前的region清空。
CMS和G1在并发标记时使用的是同一个算法: 三色标记法 ,使用白灰黑三种颜色标记对象。白色是未标记;灰色自身被标记,引用的对象未标记;黑色自身与引用对象都已标记。
在remark过程中,黑色指向了白色,如果不对黑色重新扫描,则会漏标。会把白色D对象当作没有新引用指向从而回收掉。
并发标记过程中,Mutator删除了所有从灰色到白色的引用,会产生漏标。此时白色对象应该被回收
产生漏标问题的条件有两个:
1.黑色对象指向了白色对象
2.灰色对象指向白色对象的引用消失
所以要解决漏标问题,打破两个条件之一即可:
为什么G1采用SATB而不用incremental update?
因为采用incremental update把黑色重新标记为灰色后,之前扫描过的还要再扫描一遍,效率太低。
G1有RSet与SATB相配合。Card Table里记录了RSet,RSet里记录了其他对象指向自己的引用,这样就不需要再扫描其他区域,只要扫描RSet就可以了。
也就是说 灰色--白色 引用消失时,如果没有 黑色--白色,引用会被push到堆栈,下次扫描时拿到这个引用,由于有RSet的存在,不需要扫描整个堆去查找指向白色的引用,效率比较高。SATB配合RSet浑然天成。
什么是GC,GC是什么意思?为什么要有GC?
为什么要有GC? 首先JAVA和ASP.NET都有GC 垃圾回收 (garbage collection, GC) 一个跟踪过程,它传递性地跟踪指向当前使用的对象的所有指针,以便找到可以引用的所有对象,然后重新使用在此跟踪过程中未找到的任何堆内存。公共语言运行库垃圾回收器还压缩使用中的内存,以缩小堆所需要的工作空间 因为你没有足够多内存,并且,你挺懒,不去自己清理内存,所以就有了 GC 什么是GC GC的全称是garbage collection,中文名称垃圾回收,是.net中对内存管理的一种功能。垃圾回收器跟踪并回收托管内存中分配的对象,定期执行垃圾回收以回收分配给没有有效引用的对象的内存。当使用可用内存不能满足内存请求时,GC会自动进行。 在进行垃圾回收时,垃圾回收器回首先搜索内存中的托管对象,然后从托管代码中搜索被引用的对象并标记为有效,接着释放没有被标记为有效的对象并收回内存,最后整理内存将有效对象挪动到一起。这就是GC的四个步骤。 由上可见,GC是很影响性能的,所以一般说来这种事情况还是尽量少发生为好。 为了减少一些性能影响,.net的GC支持对象老化,或者说分代的概念,代是对象在内存中相对存现时期的度量单位,对象的代数或存现时期说明对象所属的代。目前.net的垃圾回收器支持三代。每进行一次GC,没有被回收的对象就自动提升一代。较近创建的对象属于较新的代,比在应用程序生命周期中较早创建的对象的代数低。最近代中的对象位于零代中。
go gc gccgo gcc GNU 之间的关系
gc 与gccgo 都是go语言标准规范的不同实现,两者包含不同的侧重点:
使用成本上gccgo远比gc更高,基于如下原因:
总结:除非真要追求高性能,否则不建议去折腾gccgo
如果一定要折腾,建议思路:基于gcc docker 镜像,编写Dockerfile,安装golang,然后使用 go build -compiler=gccgo 。
相关资源:
当前题目:go语言gc为什么不分代,gc为什么要分代
本文URL:http://cdiso.cn/article/hsggso.html