it_worker365

   ::  ::  ::  ::  :: 管理

垃圾 -> 程序不用的内存空间

gc要做什么 -> 找到垃圾,回收垃圾

为什么要回收 -> 因为只分配不释放会内存泄漏,占满内存,系统崩溃

释放需要注意什么 -> 正确释放 -> 防止悬垂指针(指向释放完毕的空间)/防止释放正在使用的空间

GC操作的基本单位是对象,对象包含对象头(对象的大小种类,根据不同gc算法所需的信息)和域(对象使用者可以引用或替换)

gc分配堆内存空间 -> mutator要求在堆中存放对象 -> 堆满进行gc -> 如果还不够则尝试增大堆

根 (全局变量,寄存器,调用栈)

gc评价标准: 吞吐量(单位时间的处理能力,比如复制算法只检查活动对象,标记清除算法检查所有活动和非活动对象,随着对象类型占比不通则效率不通),最大暂停时间(因为执行gc而导致的暂停执行的最长时间),堆使用率(复制能用一般,标记清除都能用),访问局部性(为了更好的利用存储器,寄存器->缓存->内存->辅助存储,将更有用的数据加载到更小但更快的存储中使用,用临机预读,引用关系对象预加载等方式提升)

标记清除

标记所有活动对象(所以标记花费的时间与活动对象的总数成正比,采用深度优先遍历),清除那些没有标记的非活动对象(遍历所有堆,所以堆越大,清除花费的时间越长,将非活动对象作为分块,连接到空闲列表,之后遍历空闲链表就可以找到可用分块了),分配(将回收的垃圾进行再利用,搜索空闲链表并寻找合适大小的分块-或者找到最合适的,或者找到第一个能装下的,最差不可用的是找最大的)

合并:在清除阶段将连续的小分块连接在一起形成一个大的分块

缺点:碎片化,分块不连续,遍历空闲链表时间不确定,可能在最头也可能在最后,因为每次都要给对象头写标识所以根写时复制不兼容

措施:多个大小不同的空闲链表,用空闲链表数据管理,或将大小相近的对象整理成固定大小的块进行管理,位图标记法,延迟清除只在分配时执行必要的遍历

引用计数器

在对象头中记录有多少程序应用了这个对象,在mutator的处理过程中通过增减计数器的值来进行内存管理,更新引用的时候,先对新引用对象的计数器+1,再对之前引用的对象-1,再更新引用关系,先+1再-1是为了防止同一个对象的时候-1被回收了就没办法+1了。

优点:

立即回收:引用计数算法中会监督在更新指针的时候是否产生垃圾,从而在产生垃圾的时候立即回收,而标记清除即使产生了算法也不立即回收,而是只会在没有分块的时候将垃圾一并回收

最大暂停时间短:只有当通过mutator更新指针时程序才会回收垃圾

没有必要沿指针查找

缺点:计数器值的增减处理繁重,计数器需要占用很多位 空间利用率下降,实现繁琐,循环引用无法回收

升级:

延迟引用计数器:从根引用的指针的变化不反映在计数器上,使用zct表,事先记录下计数器值在def_ref_cnt函数作用下变为0的对象。如果没空间了再scan_zct把所有通过根直接引用的对象的计数器都进行增量,反应到计数器值上

优点是延迟了根引用计数器的技术,将垃圾一并回收,减轻了根引用频繁变化而导致的计数器增减锁带来的额外负担

缺点是引用计数器的增减有延迟,垃圾无法马上回收

strcky:

减少计数器位宽,

1位引用计数法

部分标记清除算法

 

posted on 2018-09-12 09:30  it_worker365  阅读(118)  评论(0编辑  收藏  举报