go 内存管理-从TCMalloc到go内存管理

TCMalloc

概念

  • 页(Page) : 页是由连续的物理地址所组成的固定大小的内存块
  • Span : 它是由一系列连续的页所组成的固定大小的区域
  • ThreadCache : 每个线程的cache,每个cache包含多个链表,每个链表的内存块大小相同,相当于给内存块大小分类
  • CentralCache : 所有线程的共享的cache,cache包含链表数量和Threadcache一致,当ThreadCache的内存块不足时,可以从CentralCache获取内存块
  • PageHeap堆内存的抽象,PageHeap存的也是若干链表,CentralCache的内存不足时,会从PageHeap获取空闲的内存Span,当CentralCache的内存过多时,会把空闲的内存块放回PageHeap中。

分配过程

TCMalloc 把对象分为3种,小对象大小:0-256KB,中对象大小:257-1MB
,大对象大小:>1MB

小对象分配顺序:

ThreadCache -> CentralCache -> HeapPage

中对象分配顺序:

直接在PageHeap选择

大对象分配:

从large span set选择合适数量的页面组成span

Go内存管理

概念

  • Page : 与TCMalloc一致
  • Span : 与TCMalloc一致
  • mcache : 类似于ThreadCache
  • mcentral:与TCMalloc中的CentralCache类似,但mcentral中每个级别的span会存两个链表,一个用来存放包含指针的对象,一个用来存放不包含指针的对象
  • mheap : mheap与TCMalloc中的PageHeap类似, 但mheap是用树结构存储,TCMlloc中使用链表,里面保存两个二叉排序树,以span的页的数量排序,一个是free,保存span空闲并且非垃圾回收的span,一个是scav,保存是空闲并且已经垃圾回收的span
  • object size : 申请内存的对象大小
  • size class : 它是size的级别
  • span class : 指span的级别
  • num of page :简称npage,Page的数量

内存分配

GO中把对象分为小对象和大对象(>32KB),而小对象分为tiny对象(1Byte~16Byte),和其他小对象

小对象 内存分配:

寻找span的流程如下:

  1. 计算对象所需内存大小size
  2. 根据size到size class映射,计算出所需的size class
  3. 根据size class和对象是否包含指针计算出span class
  4. 获取该span class指向的span
  5. 从span分配对象空间,从span找到第一个可用的内存块
  6. mcache向mcentral申请span,mcentral和mcache一样,都是0~133这134个span class级别,但每个级别都保存了2个span list,即2个span链表 nonempty:这个链表里的span,所有span都至少有1个空闲的对象空间。这些span是mcache释放span时加入到该链表的。empty:这个链表里的span,所有的span都不确定里面是否有空闲的对象空间。当一个span交给mcache的时候,就会加入到empty链表。过程: mcache向mcentral申请span时,mcentral会先从nonempty搜索满足条件的span,如果没有找到再从emtpy搜索满足条件的span,然后把找到的span交给mcache。
  7. mecentral向mheap申请span:mcentral需要向mheap提供需要的内存页数和span class级别,然后它优先从free中搜索可用的span。如果没有找到,会从scav中搜索可用的span。如果还没有找到,它会向OS申请内存,再重新搜索2棵树,必然能找到span。如果找到的span比需要的span大,则把span进行分割成2个span,其中1个刚好是需求大小,把剩下的span再加入到free中去,然后设置需要的span的基本信息,然后交给mcentral。

大对象分配

与mcentral向mheap申请内存的相同

猜你喜欢

转载自blog.csdn.net/csxylrf/article/details/130490052
go
今日推荐