垃圾回收算法

news/2024/9/28 13:13:04

垃圾回收算法分为跟踪式垃圾回收(Tracing garbage collection)和引用计数(Reference counting)两大类。

跟踪式垃圾回收

跟踪式垃圾回收的基本原理是先认定一些对象为root,比如全局变量和栈变量。然后跟踪(trace)哪些对象是从这些root可达的,而剩下的从这些root不可达的对象就是garbage,可以被回收。

最简单的方法就是mark-and-sweep。首先stop the world,然后从root开始标记哪些对象是从root可达的(mark),最后把那些没有标记的对象回收(sweep)。缺点就是需要stop the world,即停止一切其他工作,只进行垃圾回收。

这篇文章说mark-and-sweep不能做到on-the-fly是因为“在不同阶段标记清扫法的标志位 0 和 1 有不同的含义,那么新增的对象无论标记为什么都有可能意外删除这个对象”:https://zhuanlan.zhihu.com/p/105495961。但是我觉得新增对象统一染成黑色,下次GC的时候所有对象都变成白色再从根开始染成黑色就行了,这样做的缺点就是新增对象要等到。

我觉得三色标记法(tri-color marking)跟mark-and-sweep基本上是一回事,里面的gray set有点像广度优先搜索的队列。新增对象需要到下次GC才能释放的问题仍然存在。

引用计数

使用引用计数进行垃圾回收时,为每个对象保存其被引用的次数,如果引用次数为0,就说明这个对象不可达,就可以被当成垃圾回收掉了。

但是引用计数法存在一些问题。引用计数法需要为每个对象额外存储引用计数,因此会增大空间开销,尤其是当对象比较小的时候。此外,引用计数法需要经常进行加减操作,而且在多线程程序中,引用计数的加减还需要是原子操作,这就引入了很高的额外时间开销。此外,如果当发现引用计数变成0之后当场将其释放掉,那么会导致程序的实时性变差,因为可能会一下子释放很多对象,不过这可以通过将释放的工作交给其他线程做来解决,但是会增加开销,并且减弱垃圾回收的及时性。

以上的问题都是开销方面的。引用计数的一个最致命的问题是,当存在循环引用时,引用计数法将无法将这些循环引用的对象释放,因为它们的引用计数都不是0。一种缓解这种情况的方法是当需要进行双向引用时(例如双向链表),将其中一个引用设置成弱引用,即只引用它,而不增加其引用计数,从而避免了一部分循环引用。但是这种方法不能完全解决循环引用的问题。还有一种方法是周期性进行跟踪式垃圾回收,将不可达的环删掉,如果环的内存占用低,可以减少进行跟踪式垃圾回收的频率。

关于如何回收环,有很多现有的研究。比较基础的是这个:

Lins, Rafael D. "Cyclic reference counting with lazy mark-scan." Information Processing Letters 44.4 (1992): 215-220.

基本原理是,一个garbage cycle只有在当一个对象的引用计数被减到非0值时才会产生,因为如果引用计数被加了,那肯定就不是garbage,如果引用计数被减到0了,就是非环的garbage。因此,当一个对象的引用计数被减到非0值时,将其作为candidate root of a garbage cycle,存入root buffer里。在合适的时机,Garbage collector会从root buffer里拿出一个candidate,从它开始进行深度优先搜索,搜到从这个root可达的所有对象,然后对这些对象的每条出边,都将其指向的对象的引用计数减一,这样如果这些对象的引用计数都减为0了,就说明没有其他外部对象引用了这些对象,这些对象就构成了一个garbage cycle,可以回收掉。如果有某个对象的引用计数不为0,就说明有某个外部对象引用了这个对象,因此就不能进行回收,要把所有引用计数复原。但是在这种情况下,这个算法的复杂度是$O(n^2)$的(图片来源是[Bacon and Rajan 2001]的Fig. 1):

最快的stop the world的好像是这个:

Bacon, David F., and Vadakkedathu T. Rajan. "Concurrent cycle collection in reference counted systems." European Conference on Object-Oriented Programming. Springer, Berlin, Heidelberg, 2001.

跟[Lins 1992]不同,[Bacon and Rajan 2001]的最坏时间复杂度是$O(N+E)$的,其中$N$是对象数,$E$是引用数。这个算法与[Lins 1992]的主要区别是,[Lins 1992]是将candidate一个一个从root buffer里拿出来处理,如果发现不能回收,那么就恢复引用计数,然后拿出下一个candidate继续处理,而[Bacon and Rajan 2001]是一次性将整个root buffer里的所有candidate一起处理,从而避免了重复减某一条边指向的对象的引用计数,从而把复杂度控制在$O(N+E)$。[Bacon and Rajan 2001]将垃圾回收分为了三个阶段:MarkRootsScanRootsCollectRoots。灰色代表可能是环的成员,黑色代表可能正在使用所以不能被释放,白色表示是garbage cycle的成员。

MarkRoots:把所有root buffer里的candidate拿出来,做深度优先搜索MarkGrayMarkGray跟[Lins 1992]一致),把所有可达的对象都标记成灰色,并且将这些对象的出边指向的对象的引用计数都减一。

ScanRoots:对每个Markgray访问到的节点,如果它是灰色的而且引用计数不为0,那么这个节点不是garbage,需要将它以及所有它可达的节点都染成黑色,并且将这些重新被染成黑色的节点的所有出边指向的节点的引用计数都加一。如果它是灰色且引用计数为0,那么就把这个节点染成白色,注意这个时候不代表这个节点就是garbage了,因为后续可能有父节点被染成黑色从而将这个节点重新染成黑色,但是由于一个节点的颜色最多改变常数次,所以不影响复杂度。

CollectRoots:经过ScanRoots之后,所有灰色节点要么被染成黑色,说明其不能被释放,要么被染成白色,说明所有引用它的节点也都是白色的,这些白色的节点都是garbage,可以被释放。

可以看出,其实这种方法也算是一种启发式的跟踪式垃圾回收。

最快的on-the-fly的好像是这个:

Paz, Harel, et al. "An efficient on-the-fly cycle collection." ACM Transactions on Programming Languages and Systems (TOPLAS) 29.4 (2007): 20-es.

这篇论文还没看。

参考文献

https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

https://en.wikipedia.org/wiki/Tracing_garbage_collection

https://en.wikipedia.org/wiki/Reference_counting

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/65753.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

sha256sum文件哈希值和直接哈希字符串的哈希值不一样

例如在文件test.txt里写入 test没有换行。 然后 sha256sum test.txt出来的结果是 f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2 test.txt但是在这个网站上 http://encode.chahuo.com/ 输入test,然后以sha256方式哈希得到的结果是 9f86d081884c7d659a2f…

F-Droid使用教程

F-Droid下载地址:https://f-droid.org/ 默认的官方源太慢了。建议更换清华源。官方教程:https://mirrors.tuna.tsinghua.edu.cn/help/fdroid/ 先打开F-Droid,进入设置->存储库点进F-Droid存储库,可能会看到一些官方镜像:如果啥也没有,可能等一段时间就会出现。 把这些…

WPF 的Image 控件 设置 Image.Source 的数据源,可能存在跨线程调用的问题。

相信很多WPF 的开发,应该都很多用到 Image 这个控件来显示图片。这个图片的来源可以来自各种各样的方式获取到。 我们的组内白板、批注的扫码的功能也用到这个去生成二维码,生成后,二维码显示不出来,由于触发到了全局捕获,界面又没有崩溃,遇到了好几个坑,记录一下。 开始…

TSCTF-J 2024 部分题目复现(未完结)

TSCTF-J 2024 部分题目复现(未完结) iPlayBingo: F12拿到answerCheck.wasm文件,同时观察js代码找到关键函数Check() 利用Wabt将answerCheck.wasm文件转为answerCheck.c和answerCheck.h文件,但此时可读性依然较差。用gcc链接成answerCheck.o文件,此时可以使用IDA反汇编。​…

7-访问控制技术原理与应用

7.1 访问控制概述 1)概念 访问控制是指对资源对象的访问者授权、控制的方法及运行机制。 访问者又称为主体,可以是用户、进程、应用程序等; 资源对象又称为客体,即被访问的对象,可以是文件、应用服务、数据等; 授权是访问者可以对资源对象进行访问的方式,如文件的读、写、…

【赵渝强老师】基于大数据组件的平台架构

在了解了大数据各个生态圈所包含的组件及其功能特性后,就可以利用这些组件来搭建一个大数据平台从而实现数据的存储和数据的计算。下图展示了大数据平台的整体架构。视频讲解如下:大数据平台的Lambda架构大数据平台的Kappa架构大数据平台的总体架构可以分为五层,分别是:数据…

ctfshow-web-信息搜集(11-17)

web11 题目提示:域名其实也可以隐藏信息,比如ctfshow.com就隐藏了一条信息。 原理:通过Dns检查查询Flag。这里可以用阿里云的网站: Dns查询网站:阿里云网站运维检测平台 (aliyun.com)web12 题目提示:有时候网站上的公开信息,就是管理员常用密码 原理:查看robots.txt文件…

几款文本编辑器横向比较

文本编辑器 大文件编辑器 程序员编辑器几款文本编辑器横向比较 关键字: 大文件、编辑器 ‍ 编辑器功能及性能比较免责声明以下列选编辑器,仅限于本人日常接触的产品,带有强烈的个人主观和随机性,未列选产品并不代表不能满足功能需求。 测试数据(特别是时间),受限于观察条…