-10 +

Golang memory malloc

介绍

Golang 源码分析主要是基于 1.5.1 的64系统版本,主要目的是:

Golang 内存模块的整体设计

Golang 的内存分配的设计起点很高,是基于 Google 自家的 tcmalloc设计的, 这个在 Golang runtime/malloc.go 的注释有详细说明。现在我基于阅读的 Golang 源码说说整体上的设计,首先我说说对于 Golang 内存模块的设计主要的作用:

高效内存管理一般的做法就是预先向操作系统分配一大块的内存,然后切块,应用程序自己管理。而垃圾收集机制就得查询到所有的对象,查看是否是可达的,这里的可达一般有两种算法,基于图的遍历算法, 基于计数器的算法,但是基于计数器的算法,要特别处理循环引用的情况。Golang 使用的基于图的遍历算法,使用 bitmap 来管理对象的状态。

说明了 Golang 的两个作用后,我们来看看联系这两功能的纽带: span。

说完了纽带,我们来看看 Golang 在内存中的整体布局,也就是 Golang 是怎么来组织整个内存的:

内存分配的重要组件

先来看看组件的整体视图:

说一说这三级设计的主要目的:

cache的作用上面说的很明白,central 的主要作用是在多个 cache 中提高 object 的利用率,避免内存浪费。

假如 cache1 获取一个 span 后,仅使用了部分 object,那么剩余空间就可能会被浪费。而回收操作将该 span 交还给 central 后, 该 span 完全可以被 cache2、cacheN 获取使用。此时,cache1 已不再持有该 span,完全不会造成问题。

heap 的作用是为了平衡各种 object size 的需求。考虑下面的情形:

某时段某种规格的 object 需求量可能激增,那么当需求过后,大量被切分成该规格的 span 就会 被闲置浪费。将归还给 heap,就可被其他需求获取,重新切分。

分配算法分析

上面已经说明了 Golang 的这个内存布局和组件,我们现在来看看分配流程:

分配流程:

释放流程:

大体上的流程都是

cache 组件 --> central 组件 --> heap 组件 --> 操作系统

注意上图中的红色部分,object size 为 8 字节的都是指针对象,所以可以作为图遍历算法的 root 对象。关于 GC 部分, 会在下一篇 blog 中来说明。

参考

关于我

85 后程序员, 比较熟悉 Java,JVM,Golang 相关技术栈, 关注 Liunx kernel,目前痴迷于分布式系统的设计和实践。 研究包括但不限于 Docker Kubernetes eBPF 等相关技术。

Blog

Code

Life

Archive