go内存管理-内存分配-学习心得
今天想分享下自己学习go内存分配的一些心得。
首先,go程序启动时需要向系统申请内存资源。内容包含三个部分

spans:指针,指向arena的指针
bitmap:垃圾回收使用
arena:真正的存储空间
这个概念大概了解即可。
go的内存管理采用的是分级管理从cache->central->heap并且采用分类分配,将对象分为0-66共67类。
通过内存管理单位mspan来进行管理,将内存分页,每页8K。
每个协程有自己的cache,当cache不够用的时候向cental申请,central不够向heap申请,heap不够向内存申请。
mcache里持有67*2个类型的mspan。每个类型的分两种。一种是需要扫描的即带指针的,一种是不需要扫描即不带指针的。主要是为了垃圾回收方便。
mheap持有67*2个类型的mcentral。每个类型也分两种。一个是需要扫描的,一种是不需要扫描的。
当某个类型的mspan不够用了,就向对应类型的mcentral申请资源。
mcentral有两个链表,一个是empty已经申请的空间,一个是noempty空闲的可以申请的空间。
申请时需要加锁,因为是全局资源,避免竞争。然后mcentral将从noempty中分配mspan,将其加入到empty中。返回并解锁。
回收的时候也一样,先加锁。然后将内存从empty中删除,加入到noempty中,然后解锁。
基本就是这么一个过程了。
分配的时候,如果小于16B并且不包含指针,使用tiny分配。16B到32K的正常分配。大于32K的有mheap分配。
以申请size为n的内存为例,分配步骤如下:
获取当前线程的私有缓存mcache
跟据size计算出适合的class的ID
从mcache的alloc[class]链表中查询可用的span
如果mcache没有可用的span则从mcentral申请一个新的span加入mcache中
如果mcentral中也没有可用的span则从mheap中申请一个新的span加入mcentral
从该span中获取到空闲对象地址并返回
欢迎和谐讨论
参考自go专家编程
第四章:内存管理 - 4.1 内存分配原理 - 《GO专家编程》 - 书栈网 · BookStack