Golang的内存分配是由golangruntime完成的,其内存分配方案借鉴了tcmalloc。
主要特点是:
本文中的元素指的是golangruntime源代码中出现的内存分配概念,即特定大小的内存块。
本文介绍了x8664架构上的内存分配。
Golang内存分配主要结构如下:
小对象是指内存大小小于16B的对象。此类对象占用Mac缓存的一小部分区域。当小区域空间不足时,它会从[tinySpanClass]指向的mspan中查找可用空间。当然,如果mcache中的span空间也耗尽了,那么mcentral会触发一个进程,用mspan来补充mcache。
小对象是指大小在(16B,32KB]之间的对象。此类对象的分配原则如下:
1.首先,将对象排序为特定的对象SpanClass根据其大小。该SpanClass的所有元素具有相同的大小
2.从[SpanClass]中查找相应的mspan,如果没有找到,则输入mcentral。.grow()—>()为mcentral分配一个大小大于32KB的新对象,直接从mheap分配,而不使用mcache或mcentral,而是使用()并指定一个SpanClass。==0表示这部分分配的空间。/p>
对于程序分配中常用的小对象分配,当mcache饥时,mcache可以获取mcentral锁并补充mspan以提高分配性能。
在x8664环境下,golang管理的有效程序虚拟地址空间实际上只有48位。标记地址空间为空闲。
Golang认为地址空间可以有四种状态:地址空间操作函数:
mheap结构有一个名为pages的成员,用于使用虚拟地址空间管理golang堆。它的类型是pageAlloc
。pageAlloc结构代表golang堆中的所有地址空间。
golang的gc过程将未使用的对象标记为未使用,但这些对象使用的地址空间是:地址空间的申请和释放都是基于golang来完成的(实际上是分块的)。扫描的最终结果只是标记要分配的特定地址空间;它实际上并不将地址空间释放给操作系统。真正的发布是后期的清理过程。
gcmark完成后,它会尝试使用sweep()来解开跨度。当应用于mspan时,它还会使用扫描来清除跨度。
mspanscrape主要包含以下功能:
如上一节所述,扫描仅将页面标记为可分配;实际释放地址空间并不是清理过程。。
实际的清理是通过ge()—>sysUnused()释放扫描到的块所代表的地址空间(将地址空间返回给操作系统使用sysUnused()使用)。
golang有两个scavenge进程:
上一篇:天下3提示内存分配不足
下一篇:内存分配与回收心得体会