go内存管理:
大致策略:
- 申请一块较大的地址空间(虚拟内存),用于内存分配及管理(golang:spans+bitmap+arena->512M+16G+512G)
- 当空间不足时,向系统申请一块较大的内存,如100KB或者1MB
- 申请到的内存块按特定的size,被分割成多种小块内存(golang:_NumSizeClasses = 67),并用链表管理起来
- 创建对象时,按照对象大小,从空闲链表中查找到最适合的内存块
- 销毁对象时,将对应的内存块返还空闲链表中以复用
- 空闲内存达到阈值时,返还操作系统
go内存分配主要有三个管理组件:
- mcache
Per-P(Processer,具体参见go中G,M,P的概念)私有cache,用于实现无锁的object分配 - mcentral
全局内存,为各个cache提供按大小划分好的span - mheap
全局内存,page管理,内存不足时向系统申请
通过将内存分配流程分为三个层级,既能保证Processer级别(mcache)的无锁分配,又能在mcentral级别实现内存全局共享,避免浪费。
go将内存申请按大小分为三种类型:tiny,small,large。tiny是小于16个byte的申请,small是小于32KB的申请,大于32KB为large,三种类型的处理方式有所不同。
结合这几篇博客理解!
Go语言——内存管理
探索 Go 语言的内存管理
垃圾回收
各个版本的垃圾回收机制:
- v1.1 STW
- v1.3 Mark STW, Sweep 并行
- v1.5 三色标记法
- v1.8 hybrid write barrier
触发gc条件:
主动gc和被动gc(分配大小超过32k的对象)
gc机制:
参考链接gc垃圾回收
三色标记 + 写屏障
三色标记:
- 初始化:所有对象最开始都是白色。
- 遍历可达对象:从 root 开始找到所有可达对象,标记为灰色,放入待处理队列。
- BFS:遍历灰色对象队列,将其引用对象标记为灰色放入待处理队列,自身标记为黑色。
- 处理完灰色对象队列,执行清扫工作。
具体实现:
从root对象开始遍历,包括全局root指针和goroutine对象指针 mark:
- 从root指针遍历其余对象;
- 因为mark执行和用户程序并行,需要记录下mark期间新分配的对象,write barrier + re-scan
- Stop TheWorld 有两个过程:(1). GC 将要开始的时候,这个时候主要是一些准备工作,比如 enable write barrier。(2).上面提到的 re-scan 过程。如果这个时候没有 stw,那么 mark 将无休止。
- 清理速度提升:span可标示分配的对象,未被span标示的可被回收。
作者:wanhf11
来源:CSDN
原文:https://blog.csdn.net/qq_17612199/article/details/80278632