垃圾回收 -标记清除算法

news2024/10/6 18:34:37

就如他的字面意思一样,由标记阶段和清除阶段构成。标记阶段是把所有的活动对象都做上标记的阶段。清除阶段是把那些没有标记的对象,也就是非活动对象回收的阶段。通过这两个阶段,就可以令不能利用的内存空间重新得到利用。

1、 标记阶段

mark_phase(){
	for(r:$roots)
		mark(*r)
}

在标记阶段中,collector会为堆里所有活动对象打上标记。为此,我们首先要标记通过根直接引用的对象。然后递归地标记通过指针数组能访问到的对象。这样就能把所有活动对象都标记上。

mark(obj){
	if(obj.mark == false)
		obj.mark = true
		for(child :children(obj))
			mark(*child)
}

如果标记未完成,则程序会在对象头部进行置位操作。这个位要分配在对象的头之中,并且能用obj.mark访问。
在这里插入图片描述

在标记阶段,程序会标记所有活动对象。毫无疑问,标记所花费的时间是与“活动对象的总数成正比”。
标记阶段结束时的堆如下图所示:

在这里插入图片描述

2、 清除阶段

在清除阶段中,collector会遍历整个堆,回收没有打上标记的对象(即垃圾),使其可以再次得到利用。

sweep_phase(){
	sweeping = $heap_start
	while(sweeping < $heap_end)
		if(sweeping.mark == true) sweeping,mark = false
		else
			sweeping.next = $free_list
			&free_list = sweeping
		sweeping += sweeping.size
}

在此出现了叫做size的域,这是存储对象大小(字节数)的域,跟mark域一样,我们事先在各对象的头中定义他们。
在清除阶段,我们使用变量sweeping遍历堆,具体来说就是从堆首地址$heap_start开始,按顺序一个个遍历对象的标志位。
设置了标志位,就说明这个对象是活动对象。活动对象必然是不能回收的。因为我们取消标志位,准备下一次的GC。
我们必须把非活动对象回收再利用。回收对象就是把对象分块,链接到被称为“空闲链表”的单向链表。在之后进行分配时只要遍历这个空闲链表,就可以找到分块了。
在清除阶段,程序会遍历所有堆,进行垃圾回收。也就是说,所花费时间与堆大小成正比。堆越大,清楚阶段所花费的时间就会越长。
在这里插入图片描述

3、分配

接下来为大家讲解分配的相关内容。这里的分配是指将回收的垃圾进行再利用。那么,分配是怎样进行的呢?也就是说,当mutator 申请分块时,怎样才能把大小合适的分块分配给mutator 呢?
如前文所述,我们在清除阶段已经把垃圾对象连接到空闲链表了。搜素空闲链表并寻找大小合适的分块,这项操作就叫作分配。执行分配的函数 new_obj()如下所示。

new_obj(size){
	chunk = pickup_chunk(size,$free_list)
	if(chunk != NULL) return chunk
	else allocation_fail()
}

这里的pickup_chunk()函数用于遍历$free_list,寻找大于等于size的分块。如果他找到和size大小相同的分块,则会直接返回改分块;如果找到比size大的分块,则会将其分割成size大小的分块和去掉size后剩余大小的分块,并把剩余的分块返回给空闲链表。

分配策略描述
First-fit发现大于等于size的分块立即返回结果
Worst-fit找出大于等于size的最大分块返回结果
Best-fit找出大于等于size的最小分块返回结果

4、合并

根据分配策略的不同可能会产生大量的小分块。但如果他们是连续的,我们就能把所有的小分块连在一起形成一个大分块。这种操作就叫做合并。

sweep_phase(){
	sweeping = $heap_start
	while(sweeping < $heap_end)
		if(sweeping.mark == true) sweeping.mark  = false
		else
			if(sweeping == $free_list + $free_list.size)
				$free_list.size += sweeping.size
			else
				sweeping.next = $free_list
				$free_list = sweeping
			sweeping += sweeping.size
}

5、优缺点

优点

  • 实现简单
  • 与保守式GC算法兼容:不会移动对象

缺点

  • 碎片化:使用过程中会逐渐产生被细化的分块,不久后就会导致无数的小分块散布在堆的各处。众所周知,Windows的文件系统也会产生这种现象。
  • 分配速度底下:因为分块不是连续的,每次分配都必须遍历空闲链表,找到足够大的分块。最糟糕的情况就是每次进行分配都得把空闲链表遍历到最后。下面将要介绍的多个空闲链表和BiBOP法都是为了能在标记清除算法中高速进行分配而想出的方法。
  • 与写时复制技术不兼容:即使没有重写对象,GC也会设置所有活动对象的标志位,这样就会频繁发生本不应该发生的复制,压迫到内存空间。

写时复制技术(copy-on-write)
在Linux等众多UNIX操作系统的虚拟存储中用的的高速化方法。比如:在Linux中复制进程,也就是使用fork函数时,大部分内存空间都不会被复制。只是复制进程,就复制了所有内存空间不太实际。因此写时复制技术只是装作复制了内存空间,实际上是将内存空间共享了。
在各个进程中访问数据时,能够访问共享内存就没什么问题了。
然而,当我们对共享内存空间进行写入时,不能重写共享内存。因为从其他程序访问时,会发生数据不一致的情况。在重写时,要复制自己私有空间的数据,对这个私有空间进行重写。复制后只访问这个私有空间,不访问贡献内存。像这样,因为这门技术是在写入时进行复制的,所以才称为写时复制技术。

6、多个空闲链表

之前的标记清除算法,我们只用到了一个空闲链表,在这个空闲链表中,对大的分块和小的分块进行了同样的处理,但这样一来,每次分配的时候都要遍历一次空闲链表来寻找合适大小的空闲链表。
因此,我们就利用分块大小不同的空闲链表,来分配不同的分块。
在这里插入图片描述

7、BiBOP法

Big Bag Of Page:将大小相近的对象整理成固定大小的块进行管理的做法。
我们把堆分割成固定大小的块,让每个块只能配置同样大小的对象。
在这里插入图片描述

BiBOP法原本是为了消除碎片化,提高堆效率而采用的方法,但像上面这样,在多个块中分散残留着同样大小的对象,反而会降低堆的使用效率。

8、位图标记

在单纯的标记清除法中,用于标记的位是被分配到各个对象的头中的,也就是说,算法是把对象和头一并处理的。所以这和写时复制技术不兼容。
对此我们有个方法,那就是只收集各个对象的标志位并表格化,不和对象一起管理,在标记的时候不在对象的头里置位,而是在这个表格中的特定场所置位。像这样集合了用于标记的位的表哥称为“位图表格”,利用这个表格进行标记的行为称为“位图标记”
在这里插入图片描述
这样做的优点就是与写时复制技术相兼容,不会产生无谓的复制。并且清除起来也更加高效。

9、延迟清除法

之前我们提到过,清除操作所花费的时间与堆大小成正比。也就是说堆越大,清除所花费的时间就越长。结果就会妨碍到mutator的处理。
延迟清除法,就是在标记操作结束后,不一并进行清除操作,而是延迟,来防止mutator长时间的暂停。
因为延迟清除法,不是一下遍历整个堆,他只在分配时执行必要的便利,所以可以压缩因清除操作导致的mutator的暂停时间。

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

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

相关文章

bazel远程缓存(Remote Cache)

原理 您可以将服务器设置为构建输出&#xff08;即这些操作输出&#xff09;的远程缓存。这些输出由输出文件名列表及其内容的哈希值组成。借助远程缓存&#xff0c;您可以重复使用其他用户的 build 中的构建输出&#xff0c;而不是在本地构建每个新输出。 增量构建极大的提升…

音频——I2S TDM 模式(六)

I2S 基本概念飞利浦(I2S)标准模式左(MSB)对齐标准模式右(LSB)对齐标准模式DSP 模式TDM 模式 文章目录 TDM formatTDM format ATDM format BTDM format C总结 TDM format TDM 分为两种常用操作模式&#xff1a;TDM A mode 和 TDM B mode, 统称为TDM mode 基于 TDM mode&#x…

Docker 容器逃逸漏洞 (CVE-2020-15257)复现

漏洞概述 containerd是行业标准的容器运行时&#xff0c;可作为Linux和Windows的守护程序使用。在版本1.3.9和1.4.3之前的容器中&#xff0c;容器填充的API不正确地暴露给主机网络容器。填充程序的API套接字的访问控制验证了连接过程的有效UID为0&#xff0c;但没有以其他方式…

7.2 项目2 学生通讯录管理:文本文件增删改查(C 版本)(自顶向下设计+断点调试) (A)

C自学精简教程 目录(必读) 该作业是 作业 学生通讯录管理&#xff1a;文本文件增删改查&#xff08;C版本&#xff09; 的C 语言版本。 具体的作业题目描述&#xff0c;要求&#xff0c;可以参考 学生通讯录管理&#xff1a;文本文件增删改查&#xff08;C版本&#xff09;。…

性能测试有哪些常见的测试指标?

一、什么是性能测试 先看下百度百科对它的定义 <font size"3">性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。</font> 我们可以认为性能测试是&#xff1a;通过在测试环境下对系统或构件的性能进…

【数据结构】栈---C语言版(详解!!!)

文章目录 &#x1f438;一、栈的概念及结构&#x1f344;1、栈的概念定义&#x1f344;2、动图演示&#x1f332;入栈&#x1f332;出栈&#x1f332;整体过程 &#x1f438;二、栈的实现&#x1f438;三、数组结构栈详解&#x1f34e;创建栈的结构⭕接口1&#xff1a;定义结构…

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉师大图书馆

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉师大图书馆

配置keil生成asm汇编文件

简介&#xff1a;ASM是汇编语言源程序的扩展名&#xff1b;程序在编译的过程中&#xff0c;会将源代码编译会汇编代码&#xff0c;一步步生成可执行文件&#xff1b; 1&#xff1a;keil中options的配置 这个语法应该是根据工程工程哪里的配置名称来的&#xff0c;也可以使用固…

历史库存储成本节约至少 50% ,OceanBase数据压缩核心技术解读

“数据是二十一世纪的石油”&#xff0c;这个观点正在逐渐成为现实&#xff0c;现在我们有各种各样的 IT 系统不断地生产着数据&#xff0c;这些数据累积起来为我们的生产生活带来了很多便利。但在挖掘这些数据价值的同时&#xff0c;大量数据的存储与计算也带来了巨大的成本&a…

TCP和UDP通信

1.通信过程 UDP 服务器sever绑定IP地址&#xff0c;关闭套接字 TCP socket套接字&#xff08;网络通信&#xff09;

站在大数据行业山顶看风景

大家好&#xff0c;我是你们的朋友王知无。 从2022年开始应很多小伙伴的邀请和咨询&#xff0c;我以个人的名义开了自己的《面向国内Top企业的大数据训练营》。最初这个过程我的内心非常忐忑&#xff0c;从备课、直播、答疑、1对1指导&#xff0c;再到同学们找工作的过程中Offe…

制造费用分摊可参考本量利分析模型!(ODOO16/15演示)

本量利分析法&#xff08;CVP&#xff09;是管理会计的一项基本管理工具&#xff0c;能比较准确地揭示成本、业务量和利润之间的数量关系​。简单理解就是把产品&#xff08;或业务&#xff09;成本分为变动成本和固定成本&#xff0c;例如&#xff1a;生产一件衣服&#xff0c…

Langchain使用介绍之outparser 和memory

上一篇博客中对Langchain中prompt进行了详细的介绍&#xff0c;此篇博客将介绍Langchain中的outparser和memory。当调用大模型生成内容时&#xff0c;返回的内容默认是string类型&#xff0c;这对于我们获取response中的某些内容信息可能会带来障碍&#xff0c;例如返回的内容本…

YOLOv8目标检测实战:TensorRT加速部署(视频教程)

课程链接&#xff1a;https://edu.csdn.net/course/detail/38956 PyTorch版的YOLOv8是先进的高性能实时目标检测方法。 TensorRT是针对英伟达GPU的加速工具。 本课程讲述如何使用TensorRT对YOLOv8目标检测进行加速和部署。 •采用改进后的tensorrtx/yolov8的代码&#xff0c;…

阻塞/非阻塞、同步/异步(网络IO)

1.阻塞/非阻塞、同步/异步(网络IO) 【思考】典型的一次 IO 的两个阶段是什么&#xff1f; 数据就绪 和 数据读写 数据就绪 &#xff1a;根据系统 IO 操作的就绪状态 阻塞 非阻塞 数据读写 &#xff1a;根据应用程序和内核的交互方式 同步 异步 陈硕&#xff1a;在处理 IO …

3D点云处理:获取最高层范围内的点(附源码)

文章目录 0. 测试效果1. 基本内容2. 代码实现文章目录:3D视觉个人学习目录微信: dhlddxB站: Non-Stop_目标:仅获取最高层范围内的点云用于后续处理0. 测试效果 红色为提取的最高层范围内的点云 1. 基本内容 要获取点云中特定高度范围内的点云,可以使用高度条件过滤的原理。…

超越编辑器的边界:掌握 Vs Code + Vim 最强操作技巧

看完这篇文章&#xff0c;从此刻开始你将成为一名真正的 “键盘侠” 作为程序员我们知道&#xff0c;当我们编写代码的时候频繁的操作鼠标是一件非常费劲的一件事&#xff0c;我们的很多时间都会浪费到去使用鼠标定位光标选中文本等等&#xff0c;要知道使用快捷键肯定是比我们…

力扣:83. 删除排序链表中的重复元素(Python3)

题目&#xff1a; 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚…

Jenkins自动构建(Gitee)

Gitee简介安装JenkinsCLI https://blog.csdn.net/tongxin_tongmeng/article/details/132632743 安装Gitee jenkins-cli install-plugin gitee:1.2.7 # https://plugins.jenkins.io/gitee/releases获取安装命令(稍作变更) JenkinsURL Dashboard-->配置-->Jenkins Locatio…

【LLM】chatglm-6B模型训练和推理

本篇文章记录下 chatglm-6B 训练和推理过程 环境&#xff1a;Ubuntu 20.04 1.13.0cu116 chatglm-6B 源代码仓库&#xff1a;链接 chatglm-6B 模型权重&#xff1a;链接 源代码及模型 clone 到本地 这里使用的是 THUDM 在 hugging face 开源的模型。 因为模型比较大&#xff…