02.1跟雨痕看go源码-内存分配(分配&回收)

bairongdong1 · · 1868 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

内存分配和垃圾回收有关,这里我们可以先看一下内存分配。
垃圾回收比较复杂,后面讲。

一开始雨痕大大说了几个基本策略:

  1. 每次从操作系统申请一大块内存(比如1MB),以减少系统调用。
  2. 将申请到的大块内存按预定大小预先切分成小块,构成链表。
  3. 为对象分配内存时,只需从大小合适的链表中提取一个小块即可。
  4. 回收对象内存时,将该小块内存重新归还到原链表,以便复用。
  5. 如果闲置内存过多,则尝试归还部分内存给操作系统,降低内存开销。

里面提到了两个概念
span: 就是1提到的大块内存被切成小块的链表。
object: 就是上面说的小块。

span的结构

内存结构预分配图
这里span虽然是按照小块的规格进行了分级,但实际上采取了比较灵活的策略,可能会在必要条件下把较大规格span的链表的一部分借给较小规格的span,实际合并时也会尝试合并相邻的span。

����golang直接采用tcmalloc的成熟架构。
cache central heap
这里做了三级缓存。

cache是每个golang里面的P搞一个,提供一个无锁分配。

然后central根据sizeclass的大小,把所有中等的object分成若干等级,然后在这里做其中一级缓存,减少计算量。。

heap则是最后一道缓存,在这里发起回收和mmap申请。

这里写图片描述

然后雨痕给了图说明的内存分布以及初始化的过程。
还顺带普及了一下内联优化。某些简单的函数块可能会被优化掉,里面该从堆分配的,却被弄到了栈分配。。。

cache部分的逻辑:

从代码中可以看出tiny&large object做了特定的处理。tiny是使用classsize=2的span,然后里面使用尽量共享空间,希望一个object能够多复用几次。用cache.tinyoffset, cache.tiny进行控制。

大对象则直接使用堆分配。。

同时还介绍了一个
systemstack(func() {
s = largeAlloc(size, uint32(flags))
})这个使用系统栈来运行的分配函数,保证全局同步。

mcentral部分的逻辑:

这个家伙内部也有两个小缓存。
这里写图片描述
这还略屌的。
仔细看代码可以知道,mcentral的细节策略还是很多的,比如先考虑nonempty再考虑empty,使用empty时要先来个msweep尝试一下。。。是在不行了才去找heap。。。

mheap部分的逻辑:

和预料的基本一致,作为最后一级的缓存。会先考虑自己的free,不行了,才考虑向系统申请。里面的freelarge是个链表在free没有的时候,会用freelarge,顺序遍历链表找出最合适(在大于目标size里面最小)的freelarge。

#
#

回收

上来就一个综述:回收不会盯着object而是整个span。
大概就是遍历span将不可达object合并到freelist,如果已经回收所有object,则将这块内存还给heap。 细节部分,这里它会考虑同右侧的span进行合并。

释放

这里的入口有sysmon发起。每5分钟都来一次。
大概就是把heap里面的free和freelarge的span list给拿出来干掉。
细节方面这里用了madvise,用来在某些场景下提升性能。

其他

大概就是还有四块系统的部分也需要垃圾回收。
它们自己内部也弄了个二级缓存。
这里就比较简单了,是fix size的,没有span、object、classsize,第一级别用了而是一个chunk,还有复用的list。。。第二级就是使用chunk。
还有个什么record的函数。
大概就是为了提高span的便利效率而做了一个数组类型的h_spans, 然后在特定条件下引发扩容,每次扩容 A*3/2 +1。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:bairongdong1

查看原文:02.1跟雨痕看go源码-内存分配(分配&回收)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1868 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传