Go内存管理

The memory hierarchy
计算机存储设备的读写入读金字塔

我们所说的内存管理是在堆上,栈不需要操作,因为是自动回收的

栈:先进后出,出栈和入栈

内存管理基于 tcmalloc (thread-caching malloc),

Page: 大小为 4kb,无论是申请还是释放内存都以 Page 为单位,也就是 4kb

Span: 内存块,由多个 Page 构成

SizeClass:

Object:

分配流程

当程序需要内存时,会像堆请求分配内存,得到响应后,堆内存会从为分配的内存中切割出一小块内存,用来分配。中间使用链表将各个小块堆内存连接起来

分配对象时,会优先在已分配(释放后)的内存中查找近似的大小块,如果没有合适的,将在未分配的堆内存中切割类似大小的内存用来分配。

当分配的内存多了起来,在每一段分配的内存中会存在未使用的内存,这就是碎片化产生的原因。那么如何将未使用的内存,也就是碎片的内存重新利用起来?

碎片化内存利用

内存对齐

CPU 访问内存时是以字长为单位,减少对内存的访问量,加大 CPU 处理的吞吐量

现在 CPU 普遍是 64 位,字长为 8 字节,32 位的CPU,字长位 4字节

内存对象

非内存对齐

TCMalloc

Google 开源内存分配

小对象分配

小对象的分配基于 page,当需要分配的对象小于单个 page 时,采用小对象分配方式

page

单个 page 占用为 4kb,

定长对象分配

变长对象分配
内存分配时,“取整”操作,如7字节的占用,就分配8字节的长度。但是分配并不是按照2的幂数,
目前所得时8, 16, 32, 48, 64, 80(等待测试),这样分配的目的是为了减少碎片化,如果按照2的幂数计算,如65字节的占用,将会分配128字节的长度,碎片化占比接近一半。

大对象分批

span

span 是一种分配单位,

RadixTree

一种树形结构