Go 语言内存分配学习笔记

Go语言运行时依靠细微的对象分割、极致的多级缓存、精准的位图管理实现了对内存的精细化管理。

一、内存分配

1、span与元素

Go语言将内存分成了67个级别的span,其中,0级代表特殊的大对象,其大小是不固定的。当具体的对象需要分配内存时,并不是直接分配span,而是分配不同级别的span中的元素。span的级别是以span中元素大小为依据。

2、Go的三级对象管理

三级管理结构:mcache、mcentral、mheap。

Go采用TCMalloc的内存分配算法的思想,每个逻辑处理器P都有一个存储了本地span缓存,,乘坐mcache.协程需要i内存直接在mcache中获取,由于同一时间只有一个goroutine运行在逻辑处理器P上,所以中间不需要加锁。mcache包含所有大小规格的mspan,但每种规格大小只包含一个。除class0外,mcache的span都来自mcantral。

mcentral 是被所有逻辑处理为P共享的。

mcentral 收集所有给定规格大小的span。每个mcentral都包含两个mspan的链表:

  • empty mspanList : 没有空闲对象或已经被mcache缓存的span链表
  • nonempty mspanList表示没有空闲对象的span 链表

除了级别0,每个级别的span都会有一个mcentral 用于管理span链表。而所有级别的这些mcentral,其实都是一个数组,由mheap进行管理。

mheap的作用不只是管理central,大对象也会直接通过mheap进行分配。

3、四级内存块管理

根据对象的大小,Go语言将堆内存分成了HeapArea、chunk、span与page 4种内存块进行管理。

  • HeapArea:内存块最大,大小与平台有关,在UNIX64位操作系统中占据64MB
  • chunk:512KB
  • span: page的整数倍
  • page:8KB

二、对象分配

内存分配时,将对象按照大小不同划分为微小对象、小对象、大对象。

  • 微小对象:<16byte.
  • 小对象: <32KB 。
  • 大对象: >32KB. mheap分配,class为0。   分配流程:mheap基数树查找->操作系统分配。

微小对象的分配流程最长,逻辑链路最复杂。

操作系统内存申请

当从基数树中查找不到可用的连续内存时,需要从操作系统中获取内存。从操作系统获取内存的代码是平台独立的。在UNIX系统中,最终使用了mmap系统调用向操作系统申请内存。

Go语言规定,每一次向操作系统申请的内存大小必须为heapArena的倍数。heapArena和平台有关的内存大小,在64位UNIX操作系统中,其大小为64MB。多申请的内存可以用于下次分配。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值