相关博文 golang中slice扩容一定是double或1.25倍吗

Go内存详解


较好博文:

图解Go语言内存分配

Go内存管理三部曲[1]- 内存分配

https://draveness.me/golang/docs/part3-runtime/ch07-memory/golang-memory-allocator/

go 内存管理 设计与实现 图解

本篇是对以上内容的学习与记录:

Go运行时的内存分配算法主要源自 Google 为 C 语言开发的TCMalloc算法,全称Thread-Caching Malloc。核心思想就是把内存分为多级管理,从而降低锁的粒度。它将可用的堆内存采用二级分配的方式进行管理:每个线程都会自行维护一个独立的内存池,进行内存分配时优先从该内存池中分配,当内存池不足时才会向全局内存池申请,以避免不同线程对全局内存池的频繁竞争。


Go在程序启动时 先向操作系统申请一块内存,并将其分配到三个区域:

  • arena区域(512GB,64位操作系统),即堆区,Go动态分配的内存都在该区域,其将内存分割成8KB大小的页,一些页组合起来称为mspan

  • bitmap区域(16GB),标识arena区域哪些地址保存了对象,并用4bit标志位表示对象是否包含指针、GC标记信息。bitmap中一个byte大小的内存对应arena区域中4个指针大小(指针大小为 8B )的内存,所以bitmap区域的大小是512GB/(4*8B)=16GB

  • spans区域(512MB):存放mspan(arena分割的页组合起来的内存管理基本单元)的指针,每个指针对应一页,所以spans区域的大小就是512GB/8KB*8B=512MB。(除以8KB是计算arena区域的页数,而最后乘以8是计算spans区域所有指针的大小。创建mspan的时候,按页填充对应的spans区域,在回收object时,根据地址很容易就能找到它所属的mspan)

mspan 是Go内存管理的基本单元,mspan是由一片连续的8KB的页组成的大块内存。这里的页和操作系统本身的页不是一回事,它一般是操作系统页大小的几倍。即mspan是一个包含起始地址、mspan规格、页的数量等内容的双端链表

细微的对象切割

极致的多级缓存

精准的位图管理

更多:

Go 内存分配器可视化指南