Go语言内存管理(一)内存分配

Go语言内存管理(一)内存分配

golang作为一种“高级语言”,也提供了自己的内存管理机制。这样一方面可以简化编码的流程,降低因内存使用导致出现问题的频率(C语言使用者尤其是初学者应该深有体会),对程序猿友好。另一方面也可以减少内存相关系统调用,提升性能。

先了解下内存管理大致策略:

申请一块较大的地址空间(虚拟内存),用于内存分配及管理(golang:spans+bitmap+arena->512M+16G+512G)

当空间不足时,向系统申请一块较大的内存,如100KB或者1MB

申请到的内存块按特定的size,被分割成多种小块内存(golang:_NumSizeClasses = 67),并用链表管理起来

创建对象时,按照对象大小,从空闲链表中查找到最适合的内存块

销毁对象时,将对应的内存块返还空闲链表中以复用

空闲内存达到阈值时,返还操作系统

以下,基于go1.9版本,看下golang内存分配实现的基本思路。

Go内存管理的实现

go的内存管理实现基于TCMalloc(Thread-Caching Malloc)。

TCMalloc是 Google 开发的多级内存分配器,具有对抗内存碎片化,适合高并发场景的特性。据称,它的内存分配速度是 glibc2.3 中实现的 malloc的数倍。

和TCMalloc相同,go的内存分配也是基于两种粒度的内存单位:span和object。span是连续的page,按page的数量进行归类,比如分为2个page的span,4个page的span等。object是span中按预设大小划分的块,也是按大小分类。同一个span中,只有一种类型(大小)的object。

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,三种类型的处理方式有所不同。

_TinySize = 16 _MaxSmallSize = 32768

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyzyj.html