【转载】golang内存分配

Go 的分配采用了类似 tcmalloc 的结构.特点: 使用一小块一小块的连续内存页, 进行分配某个范围大小的内存需求. 比如某个连续 8KB 专门用于分配 17-24 字节,以此减少内存碎片. 线程拥有一定的 cache, 可用于无锁分配.

同时 Go 对于 GC 后回收的内存页, 并不是马上归还给操作系统, 而是会延迟归还, 用于满足未来的内存需求.

e7c619050aa14e17a7dd70f171a77c8f~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 

在 1.10 以前 go 的堆地址空间是线性连续扩展的, 比如在 1.10(linux amd64)中, 最大可扩展到 512GB. 因为 go 在 gc 的时候会根据拿到的指针地址来判断是否位于 go 的 heap 的, 以及找到其对应的 span, 其判断机制需要 gc heap 是连续的. 但是连续扩展有个问题, cgo 中的代码(尤其是 32 位系统上)可能会占用未来会用于 go heap 的内存. 这样在扩展 go heap 时, mmap 出现不连续的地址, 导致运行时 throw.

在 1.11 中, 改用了稀疏索引的方式来管理整体的内存. 可以超过 512G 内存, 也可以允许内存空间扩展时不连续.在全局的 mheap struct 中有个 arenas 二阶数组, 在 linux amd64 上,一阶只有一个 slot, 二阶有 4M 个 slot, 每个 slot 指向一个 heapArena 结构, 每个 heapArena 结构可以管理 64M 内存, 所以在新的版本中, go 可以管理 4M*64M=256TB 内存, 即目前 64 位机器中 48bit 的寻址总线全部 256TB 内存.

e4ce6fd5dcce4992acce50474924fa66~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

go 的内存分配类似于 tcmalloc, 采用了 span 机制来减少内存碎片. 每个 span 管理 8KB 整数倍的内存, 用于分配一定范围的内存需求.

点赞
收藏

评论区

加载中...

相关推荐

常用内核架构

本文分享自天翼云开发者社区《》,作者:JackW宏内核应用程序调用内存分配的API(应用程序接口)函数。处理器切换到特权模式,开始运行内核代码。内核里的内存管理代码按照特定的算法,分配一块内存。把分配的内存块的首地址,返回给内存分配的API函数。内存分配的

Linux页框分配器之内存碎片化整理

页框分配器在慢速分配中包括内存碎片化整理和内存回收,代码如下:static inline struct page __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,      struct alloc_context ac){  page  __alloc_

Linux 内核 VS 内存碎片 (上)

(外部)内存碎片是一个历史悠久的Linux内核编程问题,随着系统的运行,页面被分配给各种任务,随着时间的推移内存会逐步碎片化,最终正常运行时间较长的繁忙系统可能只有很少的物理页面是连续的。由于Linux内核支持虚拟内存管理,物理内存碎片通常不是问题,因为在页表的帮助下,物理上分散的内存在虚拟地址空间仍然是连续的(除非使用大页),但对于需要从内核线性

Go语言内存管理(一)内存分配

Go语言内存管理(一)内存分配golang作为一种“高级语言”,也提供了自己的内存管理机制。这样一方面可以简化编码的流程,降低因内存使用导致出现问题的频率(C语言使用者尤其是初学者应该深有体会),对程序猿友好。另一方面也可以减少内存相关系统调用,提升性能。先了解下内存管理大致策略:申请一块较大的地址空间(虚拟内存),用于内存分配及管

Spark 内存分配

Spark内存分配博客分类:sparkSpark1.5堆内存分配(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.cnblogs.com%2Fdreamfly2016%2Fp%2F5720180.html)

Redis内存碎片率

一、内存碎片率mem\_fragmentation\_ratioused\_memory\_rss/used\_memoryused\_memory:Redis使用其分配器分配的内存大小used\_memory\_rss:操作系统分配给Redis实例的内存大小,表示该进程所占物理内存的大小两者包括了实际缓存占用的内存和