Go 语言内存分配学习笔记

Posted Kris_u

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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。多申请的内存可以用于下次分配。

以上是关于Go 语言内存分配学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

Go 语言内存分配学习笔记

go语言学习笔记 — 基础 — 基本语法 — 常量与变量 — 变量的生命周期:变量逃逸分析 —— go编译器自动决定变量的内存分配方式(堆还是栈),提高程序运行效率

go语言学习笔记 — 基础 — 复合数据类型 — 结构体:实例化结构体 — 为结构体分配内存并初始化

go语言学习笔记 — 基础 — 基本语法 — 常量与变量 — 变量的生命周期:堆(heap)

Go 内存分配的学习

Go 内存分配的学习