文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

go语言有垃圾回收吗

2023-05-14 19:32

关注

go语言有垃圾回收。Go语言自带垃圾回收机制(GC);GC通过独立的进程执行,它会搜索不再使用的变量,并将其释放。在计算中。内存空间包含两个重要的区域:栈区 (Stack) 和堆区 (Heap);栈区一般存储了函数调用的参数、返回值以及局部变量,不会产生内存碎片,由编译器管理,无需开发者管理;而堆区会产生内存碎片,在Go语言中堆区的对象由内存分配器分配并由垃圾收集器回收。

go语言有垃圾回收吗

本教程操作环境:windows7系统、GO 1.18版本、Dell G3电脑。

Go语言自带垃圾回收机制(GC)。GC 通过独立的进程执行,它会搜索不再使用的变量,并将其释放。需要注意的是,GC 在运行时会占用机器资源。

Go 语言中的垃圾回收机制 GC 详解

在计算机科学中,垃圾回收 (Garbage Collection 简称 GC) 是一种自动管理内存的机制,垃圾回收器会去尝试回收程序不再使用的对象及占用的内存

程序员受益于 GC,无需操心、也不再需要对内存进行手动的申请和释放操作,GC 在程序运行时自动释放残留的内存
GC 对程序员几乎不可见,仅在程序需要进行特殊优化时,通过提供可调控的 API,对 GC 的运行时机、运行开销进行把控的时候才得以现身

在计算中,内存空间包含两个重要的区域:栈区 (Stack) 和堆区 (Heap);栈区一般存储了函数调用的参数、返回值以及局部变量,不会产生内存碎片,由编译器管理,无需开发者管理;而堆区会产生内存碎片,在 Go 语言中堆区的对象由内存分配器分配并由垃圾收集器回收。【相关推荐:Go视频教程、编程教学】

通常,垃圾回收器的执行过程划分为两个半独立的组件:

一、内存管理和分配

当内存不再使用时,Go 内存管理由其标准库自动执行,即从内存分配到 Go 集合。内存管理一般包含三个不同的组件,分别是用户程序 (Mutator)、分配器 (Allocator) 和收集器 (Collector),当用户程序申请内存时,它会通过内存分配器申请新内存,而分配器会负责从堆中初始化相应的内存区域

1.png

1.1 内存分配器的分配方法

在编程语言中,内存分配器一般有两种分配方法:

线性分配器

线性分配 (Bump Allocator) 是一种高效的内存分配方法,但是有较大的局限性。当用户使用线性分配器时,只需要在内存中维护一个指向内存特定位置的指针,如果用户程序向分配器申请内存,分配器只需要检查剩余的空闲内存、返回分配的内存区域并修改指针在内存中的位置;

虽然线性分配器有较快的执行速度以及较低的实现复杂度,但线性分配器无法在内存释放后重用内存。如下图,如果已经分配的内存被回收,线性分配器无法重新利用红色的内存

2.png

因此线性分配器需要与适合的垃圾回收算法配合使用

以上算法可以通过拷贝的方式整理存活对象的碎片,将空闲内存定期合并,这样就能利用线性分配器的效率提升内存分配器的性能了

空闲链表分配器

空闲链表分配器 (Free-List Allocator) 可以重用已经被释放的内存,它在内部会维护一个类似链表的数据结构。当用户程序申请内存时,空闲链表分配器会依次遍历空闲的内存块,找到足够大的内存,然后申请新的资源并修改链表

3.png

空闲链表分配器常见有四种策略:

其中第四中策略与 Go 语言中使用的内存分配策略相似

4.png

该策略会将内存分割成由 4、8、16、32 字节的内存块组成的链表,当我们向内存分配器申请 8 字节的内存时,它会在上图中找到满足条件的空闲内存块并返回。隔离适应的分配策略减少了需要遍历的内存块数量,提高了内存分配的效率

1.2 Go 中的内存分配

一张图展示内存分配组成:

在这里插入图片描述

在 Go 语言中,堆上的所有对象都会通过调用 runtime.newobject 函数分配内存,该函数会调用 runtime.mallocgc 分配指定大小的内存空间,这也是用户程序向堆上申请内存空间的必经函数

func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
	mp := acquirem()
	mp.mallocing = 1

	c := gomcache()
	var x unsafe.Pointer
	noscan := typ == nil || typ.ptrdata == 0
	if size <= maxSmallSize {
		if noscan && size < maxTinySize {
			// 微对象分配
		} else {
			// 小对象分配
		}
	} else {
		// 大对象分配
	}

	publicationBarrier()
	mp.mallocing = 0
	releasem(mp)

	return x}

从代码中可以看出 runtime.mallocgc 根据对象的大小执行不同的分配逻辑,根据对象大小将它们分成微对象、小对象和大对象

6.png

小分配

对于小于 32kb 的小分配,Go 会尝试从 mcache 的本地缓存中获取内存,该缓存处理一个跨度列表 (32kb 的内存块) mspan

7.png

每个线程 M 都分配给一个处理器 P,一次最多处理一个 goroutine。在分配内存时,当前的 goroutine 将使用其当前的本地缓存 P 来查找 span 列表中第一个可用的空闲对象

大分配

Go 不使用本地缓存管理大型分配。这些大于 32kb 的分配被四舍五入到页面大小,页面直接分配到堆中

8.png

二、垃圾回收

在 Go 语言中,垃圾回收器实现的算法是一个并发的三色标记和扫描收集器

垃回收器与 Go 程序同时运行,因此需要通过一种写屏障算法来检测内存中的潜在变化。启动写屏障的唯一条件是在短时间内停止程序,即 “Stop the World”

9.png

写屏障的目的是允许收集器在收集期间保持堆上的数据完整性

2.1 实现原理

Go 语言的垃圾收集可以分成清除终止、标记、标记终止和清除四个不同的阶段,其中两个阶段会产生 Stop The World (STW)

10.png

清除终止阶段

标记阶段 (STW)

标记终止阶段 (STW)

清理阶段

2.2 三色标记法

三色标记算法将程序中的对象分成白色、黑色和灰色三类:

三色标记垃圾收集器的工作原理很简单,可以将其归纳成以下几个步骤:

11.png

以上就是go语言有垃圾回收吗的详细内容,更多请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯