tmcalloc
参考链接
分配内存策略:全局缓存堆 + 进程私有缓存
- 对于小容量的内存申请,优先尝试进程私有缓存,若私有缓存不足,则向全局缓存申请。
- 对于大容量的内存申请,直接向全局缓存申请。
- 进程私有缓存:单链表数组,默认分配86个大小不同的块,每个块上的数组使用才初始化。
- 全局缓存堆:单链表数组,一共会分配256个不同大小的块,1 page = 4k,链表对应数组每个元素page递增。
- span:一个span可以包含几个连续分页,span的状态:未分配、作为大对象分配、作为小对象分配。
golang 内存管理
和tcmalloc的区别:
- 局部缓存不针对进程或线程,而是分配给P(goroutine)
golang的gc会stop the world
golang 变量分配:
小内存变量直接分配在栈,若内存不够则在堆分配
- 小内存若在函数中被返回,有可能分配在堆
- 大内存变量直接在堆分配
内存关键数据结构:
- mcache:goroutine cache,可以认为是 local cache。
- mcentral:全局cache,mcache 不够用的时候向 mcentral 申请。
- mheap:当mcentral 也不够用的时候,通过 mheap 向操作系统申请。
mcache:
- 好处:内存分配不会涉及锁竞争。
- 链表数组结构,如果内存不够时,会向mcentral申请。
- mspam 数组进行管理。
mcentral:
- 链表数组结构,如果内存不够时,会向mcentral申请。
- 会涉及到锁竞争。
- mspan list 管理。
mheap:
- 在系统初始化的时候会堆mheap进行申请和初始化。
- 如果内存不够,会向系统内存申请。
对象分配内存的主要流程:
- object size > 32K,则使用 mheap 直接分配。
- object size < 16K,直接使用mcache直接分配。
- object size > 16K && object size < 32K,先使用 mcache 中对应的 size class 分配。 如果 mcache 对应的 size class 的 span 已经没有可用的块,则向 mcentral 请求。 如果 mcentral 也没有可用的块,则向 mheap申请,并切分。 如果 mheap 也没有合适的 span,则想操作系统申请。
内存回收流程:
- mcache 归还内存分两部分:归还mcentral内存,可能涉及锁竞争;除此之外,归还到mheap,直接插入链表头。
- mcentral 归还mheap。
- mheap 定时归还系统内存。
各个版本的垃圾回收机制:
- v1.1 STW
- v1.3 Mark STW,Sweep 并行
- v1.5 三色标记法
- v1.8 hybrid write barrier
触发gc条件:
- 主动gc和被动gc(分配大小超过32k的对象)
gc机制:
三色标记:
- 初始化:所有对象最开始都是白色。
- 遍历可达对象:从 root 开始找到所有可达对象,标记为灰色,放入待处理队列。
- BFS:遍历灰色对象队列,将其引用对象标记为灰色放入待处理队列,自身标记为黑色。
- 处理完灰色对象队列,执行清扫工作。
具体实现:
原文链接:https://www.f2er.com/go/187188.html