go 内存管理 设计与实现 图解

本文详细介绍了Go语言的内存管理机制,包括内存的申请、释放以及不同大小对象的管理策略。文章讨论了span、mallocgc、heap等关键概念,并解析了不同大小对象(<=16b, <=32kb, >32kb)的分配过程,同时涉及了包含指针的对象内存管理。此外,还涵盖了内存分配与垃圾收集的关系,以及heap的结构和工作原理。" 111654931,9758747,webpack 深入理解:配置、loader 和插件全面解析,"['webpack', '前端开发', 'loader', 'plugins', 'vue.js']
摘要由CSDN通过智能技术生成

go 内存管理

以后都在 github 更新,请戳 go 内存管理实现

目录

相关位置文件

概览

span

mallocgc

heap

更多资料

相关位置文件

  • src/runtime/mgc.go
  • src/runtime/malloc.go
  • src/runtime/mgcmark.go
  • src/runtime/mbitmap.go

概览

overview

当你在 go 中申请内存空间时, 申请的内存空间直接来源于 span, 通常一个 span 存储了 8kb 大小的空间, span 中的每个元素大小是 N, 那么一个 span 就含有 8kb / N 个元素, alloc 会在 span 中获取一个空闲的元素

mcache 缓存了一些 span , mcache 是每个线程(在Go 里, 是每个 P)独有的一个线程缓存的结构, 在当前的 P 中缓存 136 个不同的 span, 每当你需要一个 span 时, 你可以在不加锁的情况下快速从这里获取到一个

如果当前需要的spanmacache 中获取不到, 则会从 mcentral 中获取一个新的 span, mcentral 存储了两个 span 的双链表, mcentral 是存储在 heap 中的全局变量, 获取时会在上述链表中查找到一个空闲的 span

如果mcentral 也获取不到, 则会从 P 的缓存中获取, P 的缓存中的的 span 是从 heap 中申请的

arena 存储了 heap 空间中的元信息, 每个 arena 对象代表了 64MB 的空间的信息, 并且还有一个 bitmap 代表当前的空间中每个字节是否需要扫描, 是否存储了指针的标记信息

Go 把heap中所有的虚拟地址映射到了 arena 数组中不同的对象中, 当你拿到一个对象的地址时, 你可以通过 (addr - base_addr) / range_length 简单的计算就获取到对应的 arena 数组索引, 从而获得 arena 对象

映射(申请内存) 是通过 mmap 系统调用 实现的, 这个申请并不会 实际占用物理存储空间

在 go 1.11 之后, 不同的 arena 中的地址不再是连续的

span

每一个 P 都存储了一个指向 mcache 的指针, 这个对象缓存了一个列表, 列表里是元素大小不同的 span

// src/runtime/mcache.go
func allocmcache() *mcache {
   
	var c *mcache
	systemstack(func() {
   
		lock(&mheap_.lock)
		c = (*mcache)(mheap_.cachealloc.alloc())
		c.flushGen = mheap_.sweepgen
		unlock(&mheap_.lock)
	})
	for i := range c.alloc {
   
		c.alloc[i] = &emptymspan
	}
	c.nextSample = nextSample()
	return c
}

numSpanClasses 默认是 136, mcache 中的 alloc 数组存储了 136 种不同的 span, alloc[2]alloc[3] 大小相同, 一个是给 没有指针的对象 (noscan ) 用的, 一个是给包含指针的对象(scan)用的, alloc[4]alloc[5] 大小相同, 以此类推

这些不同的 span 元素大小从 8bytes 到 32kb 不等, 列表中的基数个用作 noscan, 偶数个用作 scan

span 并没有在程序启动时就初始化好, 它是动态申请的(在你申请对应大小空间的时候进行申请的)

在这里插入图片描述

// src/runtime/sizeclasses.go
// class  bytes/obj  bytes/span  objects  tail waste  max waste  min align
//     1          8        8192     1024           0     87.50%          8
//     2         16        8
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值