图解 Go 内存管理与内存清理
共 2557字,需浏览 6分钟
· 2020-08-19
![](https://filescdn.proginn.com/fc5112510b408fd62a051331d8bc6ea2/eb998d218239cab31dbd12f42c027253.webp)
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.
这篇文章基于 Go 1.13 版本。有关内存管理的讨论在我的文章 ”Go:内存管理与分配[1] ” 中有解释。
清理内存是一个过程,它能够让 Go 知道哪些内存段最近可用于分配。但是,它并不会使用将位置 0 的方式来清理内存。
将内存置 0
将内存置 0 的过程 —— 就是把内存段中的所有位赋值为 0 —— 是在分配过程中即时执行的。
Zeroing the memory
但是,我们可能想知道 Go 采用什么样的策略去知道哪些对象能够用于分配。由于在每个范围内有一个内部位图 allocBits
,Go 实际上会追踪那些空闲的对象。让我们从初始态开始来回顾一下它的工作流程,
Free objects tracking with allocBits
就性能角度来看,allocBits
代表了一个初始态并且会保持不变,但是它会由 freeIndex
(一个指向第一个空闲位置的增量计数器)所协助。
然后,第一个分配就开始了:
Free objects tracking with allocBits
分配过程将会再一次出现,之后, GC 将会启动去释放不再被使用的内存。在标记期间,GC 会用一个位图 gcmarkBits
来跟踪在使用中的内存。让我们通过我们运行的程序以相同的示例为例,在第一个块不再被使用的地方。
Memory tracking during the garbage collector
![](https://filescdn.proginn.com/07960333bde2a1e6702dee2478a7d375/752011a3599e8ee58f1195bc779bf4b9.webp)
Sweeping a span
清理阶段
Go 提供了两种方式来清理内存:
使用一个工作程序在后台等待,一个一个的清理这些范围。 当分配需要一个范围的时候即时执行。
关于后台工作程序,当开始运行程序时,Go 将设置一个后台运行的 Worker(唯一的任务就是去清理内存),它将进入睡眠状态并等待内存段扫描:
Background sweeper
![](https://filescdn.proginn.com/66ae5a68e571197fc396770cab470343/1749fe60874b44e859f829dee3d70f84.webp)
Background sweeper
![](https://filescdn.proginn.com/a1e5cfa01b2a1dbe7b5101d85c7cf96f/fb603334b8cbe4355841cb5bee336210.webp)
Spans are released to the central list
![](https://filescdn.proginn.com/c29886d811eb3a898156f4f6a0716c78/524b3ad7e13c5f592b2f133bb4ee5a84.webp)
Sweep span on the fly during allocation
与 GC 周期的冲突
正如之前看到的,由于后台只有一个 worker 在清理内存块,清理过程可能会花费一些时间。但是,我们可能想知道如果另一个 GC 周期在一次清理过程中启动会发生什么。在这种情况下,这个运行 GC 的 Goroutine 就会在开始标记阶段前去协助完成剩余的清理工作。让我们举个例子看一下连续调用两次 GC,包含数千个对象的内存分配的过程。
Sweeping must be finished before a new cycle
via:https://medium.com/a-journey-with-go/go-memory-management-and-memory-sweep-cc71b484de05作者:Vincent Blanchon[2]译者:
[3]校对:polaris1119[4]
本文由 GCTT[5] 原创编译,Go 中文网[6] 荣誉推出
参考资料
Go:内存管理与分配: https://medium.com/a-journey-with-go/go-memory-management-and-allocation-a7396d430f44
[2]Vincent Blanchon: https://medium.com/@blanchon.vincent
[3]sh1luo: https://github.com/sh1luo
[4]polaris1119: https://github.com/polaris1119
[5]GCTT: https://github.com/studygolang/GCTT
[6]Go 中文网: https://studygolang.com/
推荐阅读
站长 polarisxu
自己的原创文章
不限于 Go 技术
职场和创业经验
Go语言中文网
每天为你
分享 Go 知识
Go爱好者值得关注