Go语言堆内存管理

Go堆内存管理

1. Go内存模型层级结构

Golang内存管理模型与TCMalloc的设计极其相似。基本轮廓和概念也几乎相同,只是一些规则和流程存在差异。

2. Go内存管理的基本概念

Go内存管理的许多概念在TCMalloc中已经有了,含义是相同的,只是名字有一些变化。

2.1 Page

与TCMalloc中的Page相同,x64架构下1个Page的大小是8KB。Page表示Golang内存管理与虚拟内存交互内存的最小单元。操作系统虚拟内存对于Golang来说,依然是划分成等分的N个Page组成的一块大内存公共池。

2.2 mspan

与TCMalloc中的Span一致。mspan概念依然延续TCMalloc中的Span概念,在Golang中将Span的名称改为mspan,1个mspan为多个Page(go中为8KB的内存大小)。1个mspan对应1个或多个大小相同的object,mspan主要用于分配对象的区块,下图简单说明了Span的内部结构。

mspan结构体如下:

go 复制代码
type mspan struct {

    next *mspan     // 在mspan链表中,指向后一个mspan

    prev *mspan     // 在mspan链表中,指向前一个mspan

    list *mSpanList // 供debug使用

    startAddr uintptr // mspan起始地址

    npages    uintptr // 当前mspan对应的page数

    manualFreeList gclinkptr // mSpanManual状态mspan中的可用对象链表

    // freeindex是slot索引,标记下一次分配对象时应该开始搜索的地址, 分配后freeindex会增加

    // 每一次分配都从freeindex开始扫描allocBits,直到它遇到一个表示空闲对象的0

    // 在freeindex之前的元素都是已分配的, 在freeindex之后的元素有可能已分配, 也有可能未分配

    freeindex uintptr

    nelems uintptr // 当前span中object数量.



    // allocCache是从freeindex位置开始的allocBits缓存

    allocCache uint64



    // allocBits用于标记哪些元素是已分配的, 哪些元素是未分配的。

    // 使用freeindex + allocBits可以在分配时跳过已分配的元素, 把对象设置在未分配的元素中.

    allocBits  *gcBits

    // 用于在gc时标记哪些对象存活, 每次gc以后allocBits都会与gcmarkBits保持一致

    gcmarkBits *gcBits



    // 清理代数,每GC1次sweepgen会+2

    // sweepgen=currrent sweepgen - 2:该span需要被清扫

    // sweepgen=currrent sweepgen - 1:该span正在被清扫

    // sweepgen=currrent sweepgen:该span已被清扫,带使用

    // sweepgen=currrent sweepgen + 1:该span在清扫开始前,仍然被缓存,需要被清扫

    // sweepgen=currrent sweepgen + 3:该span已被清扫,仍然被缓存

    sweepgen    uint32

    divMul      uint32        // for divide by elemsize

    allocCount  uint16        // 已分配对象的数量

    spanclass   spanClass

    state       mSpanStateBox

    needzero    uint8         // 在分配前需要清零

    elemsize    uintptr       // 对象大小

    limit       uintptr       // span数据末尾

    speciallock mutex         // specials链表的锁

    specials    *special      // 根据object偏移量排序的special链表.

}

mspan的allocBits是一个bitmap,用于标记哪些元素是已分配的, 哪些元素是未分配的。通过使用allocBits已经可以达到O(1)的分配速度,但是go为了极限性能,对其做了一个缓存allocCache,allocCache是从freeindex开始的allocBits缓存。

2.3 Size Class

Golang内存管理针对衡量内存的概念又更加详细了很多,这里面介绍一些基础的有关内存大小的名词及算法。

  1. Object Class是指协程应用逻辑一次向Go内存申请的对象Object大小。Object是Golang内存管理模块针对内存管理更加细化的内存管理单元。一个Span在初始化时会被分成多个Object。

    比如Object Size是8B(8字节)大小的Object,所属的Span大小是8KB(8192字节),那么这个Span就会被平均分割成1024(8192/8=1024)个Object。

    逻辑层从Golang内存模型取内存,实则是分配一个Object出去。为了更好的让读者理解,这里假设了几个数据来标识Object Size 和Span的关系

    加载更多

相关推荐
峥嵘life11 分钟前
Android16 311Y3 EAP-TLS 网络连接失败分析与修复总结
android·开发语言·人工智能·php
笃行35042 分钟前
SQLServer数据迁移之后,那张报表还能不能秒出
后端
LucianaiB1 小时前
别再被 AI 骗了:我把腾讯云 4 个 Skill 做成了个「AI 打假侦探」,过程的一个小配置坑惨了我
后端
candyTong2 小时前
Claude Code 如何恢复一段会话
后端·架构·ai编程
mqiqe3 小时前
AgentScope Java Harness:4. 双层记忆系统 让 Agent 拥有真正的“长期大脑“
java·开发语言
gugucoding3 小时前
46. 【Java】JUC并发工具:让并发更简单
java·开发语言
En^_^Joy3 小时前
Django项目配置全攻略:settings配置文件
后端·python·django
Nebula_g3 小时前
JavaSE基础语法:面向对象高级(代码中的成分)
java·开发语言·编程·javase·技术栈·高级语法
for_ever_love__4 小时前
python基础语法学习: 异常的传递性
开发语言·python·学习
依然鸣4 小时前
PTA团体程序设计天梯赛L1真题讲解L1-077-080
开发语言·c++·算法·深度优先·pat考试·图论