源自 Monibuca 流媒体服务器
一棵树,
一棵树,
管住每一个字节
GoMem 是为 Go 打造的高性能内存分配器。它用单棵 Treap同时维护空闲块的 地址顺序与大小顺序:分配约 12ns,释放自动合并相邻块,节点对象池化复用, 零 GC 压力。
- ~12ns单次分配
- 0allocs/op
- 408×mmap 创建提速
- -99.98%初始内存占用
How it works
看懂这棵树:分配与回收的全过程
下面的动画由 allocator.go 的逐行 JS 移植驱动,每一次比较、旋转、摘除、合并都会被真实地播放出来。
01
一棵树,两种秩序
每个空闲块是一个节点。横向按 Start 构成二叉搜索树(中序 = 地址顺序),便于找相邻块;纵向按 size 通过旋转维持堆序,小块上浮。
02
分配:找 → 摘 → 切 → 插
find 沿树寻找够大的块并尽量向左找更贴合的;选中后旋转下沉成叶子再摘除,切下头部 size 字节,剩余部分重新插入。
03
回收:找邻居 → 合并 → 插
按地址在树中查找 End == offset 的左邻与 Start == offset+size 的右邻,能合并就合并,被吞并的节点回到对象池,避免 GC。
访问路径
候选块
选中/删除
旋转
插入/合并结果
相邻块
已分配的内存块
暂无
操作记录
Features
为高吞吐场景而生
Treap
多种分配策略
默认单棵 Treap,分配快 77–86%;也可用 twotree 标签切换为双 AVL 树,Find 快一倍。
Buddy
伙伴分配器
通过 enable_buddy 启用 Buddy 系统做内存池化,大块内存按 2 的幂高效复用。
RM
可回收内存
RecyclableMemory 批量分配、一次性回收,比关闭时快 53%,内存占用更低。
Scale
可扩展分配器
ScalableMemoryAllocator 空间不足时自动扩容子分配器,Borrow 仅需 ~5ns。
Reader
零拷贝 Reader
多缓冲区读取器,跨 buffer 读取、Skip、Range、LEB128 解码均无需拷贝。
mmap
mmap + 透明大页
enable_mmap 惰性占用物理内存;Linux 上自动开启 THP,显著降低 TLB miss。
Benchmarks
数字说话
Apple M2 Pro (ARM64) · Go 1.23.0
单树 vs 双树:分配耗时 ns/op,越短越好
MMAP:分配器创建 16MB
317.2µs默认 · 16,777,405 B
→
777nsmmap · 216 B
408×创建更快
59.8%整体更快 (geomean)
86.6%内存减少 (geomean)
ScalableMemoryAllocator
5.4nsBorrow
13.2nsMalloc
23.3nsFreeRest
0 B每次操作堆分配
Get started
三行代码上手
package main
import "github.com/langhuihui/gomem"
func main() {
// 创建可扩展分配器
allocator := gomem.NewScalableMemoryAllocator(1024)
buf := allocator.Malloc(256) // 分配
copy(buf, []byte("Hello, World!")) // 使用
allocator.Free(buf) // 释放(自动与相邻空闲块合并)
}
allocator := gomem.NewScalableMemoryAllocator(1024)
buf := allocator.Malloc(1024)
part1 := buf[0:256]
part2 := buf[256:512]
part3 := buf[512:1024]
allocator.Free(part1) // 可以只释放其中一段
allocator.Free(part2) // 与 part1 合并成 [0, 512)
copy(part3, []byte("still usable"))
allocator.Free(part3) // 全部归还,树重新回到一个节点
allocator := gomem.NewScalableMemoryAllocator(1024)
rm := gomem.NewRecyclableMemory(allocator)
buf1 := rm.NextN(128)
buf2 := rm.NextN(256)
copy(buf1, []byte("Buffer 1"))
copy(buf2, []byte("Buffer 2"))
rm.Recycle() // 一次性回收全部内存
# 双 AVL 树实现(Find 更快)
go build -tags=twotree
# 启用伙伴分配器做内存池化
go build -tags=enable_buddy
# 关闭可回收内存特性
go build -tags=disable_rm
# mmap 分配(Linux 自动启用透明大页 THP)
go build -tags=enable_mmap