面试题答案
一键面试堆内存分配基本过程
- 内存请求:当Go程序中通过
new
、make
等操作请求分配堆内存时,运行时系统开始处理该请求。 - mcentral查找:运行时首先会在
mcentral
结构中查找合适的内存块。mcentral
是管理某一种大小规格内存块的结构,每个mcentral
负责管理一种特定大小的对象。如果mcentral
中有可用的内存块,就直接从这里获取。 - mheap分配:如果
mcentral
中没有合适的内存块,就会向mheap
请求分配。mheap
是Go运行时堆内存管理的核心结构,它管理着整个堆内存。mheap
会从大的空闲内存区域中切分出合适大小的内存块给mcentral
,然后mcentral
再将其分配给请求的mspan
(mspan
是实际管理内存块的结构)。 - 对象分配:
mspan
将分配到的内存块划分成一个个小的对象,并分配给程序使用。
提高分配效率的管理方式
- 分级管理:通过
mheap
、mcentral
和mspan
的分级管理结构,使得不同大小的内存请求可以高效地被处理。mheap
负责管理大的内存区域,mcentral
负责管理特定大小规格的内存块,mspan
负责实际的对象分配,这种结构减少了内存碎片,提高了内存分配效率。 - 缓存机制:Go运行时使用了缓存机制。例如,每个
mspan
都有一个freelist
,用于缓存已释放的对象,下次分配同类型对象时可以直接从freelist
中获取,减少了从mcentral
或mheap
获取内存的开销。同时,mcentral
也会缓存一定数量的空闲mspan
,提高分配效率。 - 无锁分配:在某些情况下,Go运行时使用无锁数据结构和算法来进行内存分配,减少了锁竞争带来的开销,提高了并发环境下的内存分配效率。例如,对于小对象的分配,
mcache
(每个M
线程都有一个mcache
,用于缓存常用大小的对象)可以在无锁的情况下快速分配内存。