这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
Go语言内置运行时(就是runtime),抛弃了传统的内存分配方式,改为自主管理,最开始是基于tcmalloc,虽然后面改动相对已经很大了。使用自主管理可以实现更好的内存使用模式,比如内存池、预分配等等,从而避免了系统调用所带来的性能问题。
Go的内存分配的大致流程如下
-
首先判定 对象是 大对象 还是 普通对象还是 小对象
-
如果是 小对象
- 从 mcache 的alloc 找到对应 classsize 的 mspan
- 如果当前mspan有足够的空间,分配并修改mspan的相关属性(nextFreeFast函数中实现)
- 如果当前mspan没有足够的空间,从 mcentral重新获取一块 对应 classsize的 mspan,替换原先的mspan,然后 分配并修改mspan的相关属性
- 如果mcentral没有足够的对应的classsize的span,则去向mheap申请
- 如果 对应classsize的span没有了,则找一个相近的classsize的span,切割并分配
- 如果 找不到相近的classsize的span,则去向系统申请,并补充到mheap中
-
如果是普通对象,逻辑大致同小对象的 内存分配
- 首先查表,以确定 需要分配内存的对象的 sizeclass,并找到 对应 classsize的 mspan
- 如果当前mspan有足够的空间,分配并修改mspan的相关属性(nextFreeFast函数中实现)
- 如果当前mspan没有足够的空间,从 mcentral重新获取一块 对应 classsize的 mspan,替换原先的mspan,然后 分配并修改mspan的相关属性
- 如果mcentral没有足够的对应的classsize的span,则去向mheap申请
- 如果 对应classsize的span没有了,则找一个相近的classsize的span,切割并分配
- 如果 找不到相近的classsize的span,则去向系统申请,并补充到mheap中
-
如果是大对象,直接从mheap进行分配
- 如果 对应classsize的span没有了,则找一个相近的classsize的span,切割并分配
- 如果 找不到相近的classsize的span,则去向系统申请,并补充到mheap中