Golang入门——内存管理

Golang入门——内存管理

概要

预申请的内存划分为spans 、 bitmap 、 arena三部分。
arena为堆区,应用区中的内存从其中分配。大小为521GB,划分成一个一个的page,每个page大小为8KB,一共有 512GB/8KB = 64M个page。
spans存放span指针,每个指针对应一个或者多个arena,span大小为 512GB/8KB * 8byte = 512MB。
bitmap由arena计算出来,主要用于GC。

span

span用于管理arena页关键的数据,每个span包含一个或者多个连续页。为满足小对象分配,会将span中的一页划分为更小的粒度,而对于超过页大小则会通过多页实现。span是内存管理的基本单位。

class

每一类代表一个固定大小的对象以及span的大小。通常class越大,span占用堆的字节数越多。每个class只能包括一个对象。
class最大值为66,即最大的对象大小为32KB,如果超过32KB,则class 为0 。

cache

mcentral是管理span的数据结构。线程需要内存时,需要想mcentral申请,为避免多线程申请内存加锁,所以为每个线程配备了span缓存,称为cache。
cache的数据结构中,定义了数组大小为class总数二倍的mspan指针数组。每种class类型都有两组span列表,第一组列表包含指针,第二组不包含,主要用于提高GC扫描效率。
根据GC是否扫描,将对象分为scan类以及noscan类,其中scan类即为包含指针的类。

central

cache为单个线程服务,而central为全局资源、多个线程服务。
当线程内存不足时向central申请,当线程释放内存时又会回收进central。
线程从central回去span的步骤:

  1. 加锁。
  2. 从nonempty列表中取出一个可用的span。
  3. 将span加入到empty列表。
  4. 将span发送给线程。
  5. 解锁
  6. 将span写入cache。

线程归还span给central

  1. 加锁。
  2. 将span从empty列表取出。
  3. 将span加入nonempty列表。
  4. 解锁。

heap

每种mcentral管理一种class,而mcentral集合存放于mheap数据结构中。

内存分配

分配对象大小分配类型
(0 , 16B)不包含指针Tiny分配
(0 , 16B)包含指针正常分配
(16B , 32KB)正常分配
(32KB , +∞ )大对象分配

申请size为n的内存流程:

  1. 获取当前线程的cache。
  2. 通过size计算出合适的class的ID。
  3. 从cache的alloc[class]链表中查询可用span。
  4. 如果有可用span,则从mcentral申请一个span加入cache。
  5. 如果没有可用span,则从mheap中申请一个新的span加入cache。
  6. 从该span中获取空闲对象地址并返回。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值