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语言学习笔记 — 基础 — 复合数据类型 — 结构体:实例化结构体 — 为结构体分配内存并初始化