Go 1.27 给 80 字节以内的分配加了专用函数,16/24 字节收益最大
原文:(Michael Matloob,2026 年 9 月 16 日)
Go 1.27 加快了 80 字节及以下对象的内存分配,提升幅度 20–30%,分配密集的程序整体最多快 1%。做法是给若干固定尺寸的分配路径各生成一个专用函数,绕开通用分配器里的部分开销。
从 newobject 到 mallocgc
堆分配最终都走运行时的 mallocgc,它需要两个参数:分配尺寸,以及对象是否含指针。编译器判定某个对象逃逸到堆上后,会插入一次 newobject 调用——这只是一层薄封装,负责取出尺寸和「是否含指针」,再转给 mallocgc。
这两项信息基本决定了分配器要做的事。尺寸之所以关键,是因为分配器按 size class 划分:
| size class | 覆盖字节数 |
|---|---|
| 1 | 1–8 |
| 2 | 9–16 |
| 3 | 17–24 |
| 4 | 25–32 |
| 5 | 33–48 |
| 6 | 49–64 |
| 7 | 65–80 |
申请 17 字节还是 24 字节,拿到的都是下一个空闲的 24 字节对象。
含指针与不含指针的对象使用两套独立的空闲链表(span),因为 GC 需要不同的记账方式。两者合起来编码成 span class:
span class = sizeClass 提交。