Golang内存管理机制.pdfVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Golang内存管理机制 golang是⼀门⾃带垃圾回收的语⾔,它的内存分配器和tmalloc(thread-caching malloc)很像,⼤多数情况下是不需要⽤户⾃⼰管理内存的。 最近了解了⼀下golang内存管理,写出来分享⼀下,不正确的地⽅请⼤佬们指出。 那么,如果⾃⼰想要实现⼀门语⾔的内存管理,应该怎么设计呢? 1.内存池: 应该有⼀个主要管理内存分配的部分,向系统申请⼤块内存,然后进⾏管理和分配。 2.垃圾回收: 当分配的内存使⽤完之后,不直接归还给系统,⽽是归还给内存池,⽅便进⾏下⼀次复⽤。⾄于垃圾回收选择标记回收,还是分代回收算法 应该符合语⾔设计初衷吧。 3.⼤⼩切分: 使⽤单独的数组或者链表,把需要申请的内存⼤⼩向上取整,直接从这个数组或链表拿出对应的⼤⼩内存块,⽅便分配内存。⼤的对象以页 申请内存,⼩的对象以块来申请,避免内存碎⽚,提⾼内存使⽤率。 4.多线程管理: 每个线程应该有⾃⼰的内存块,这样避免同时访问共享区的时候加锁,提升语⾔的并发性,线程之间通信使⽤消息队列的形式,⼀定不要使 ⽤共享内存的⽅式。提供全局性的分配链,如果线程内存不够⽤了,可向分配链申请内存。 这样的内存分配设计涵盖了⼤部分语⾔的,上⾯的想法其实是把golang语⾔内存分配抽象出来。其实Java语⾔也可以以同样的⽅式理解。内 存池就是JVM堆,主要负责申请⼤块内存;多线程管理⽅⾯是使⽤栈内存,每个线程有⾃⼰独⽴的栈内存进⾏管理。 golang 内存分配器 golang内存分配器主要包含三个数据结构:MHeap,MCentral以及MCache 1.MHeap:分配堆,主要是负责向系统申请⼤块的内存,为下层MCentral和MCache提供内存服务。他管理的基本单位是MSpan(若⼲连续内 存页的数据结构) type MSpan struct { MSpan *next; MSpan *prev; PageId start; // 开始的页号 uintptr npages; // 页数 ….. }; 可以看出MSpan是⼀个双端链表的形式,⾥⾯存储了它的⼀些位置信息。 通过⼀个基地址+(页号*页⼤⼩),就可以定位到这个MSpan的实际内存空间。 type MHeap struct { lock mutex; free [_MaxMHeapList] mSpanList // free lists of given length freelarge mSpanList // free lists length = _MaxMHeapList busy [_MaxMHeapList] mSpanList // busy lists of large objects of given length busylarge mSpanList }; free数组以span为序号管理多个链表。当central需要时,只需从free找到页数合适的链表。large链表⽤于保存所有超出free和busy页数限制 的MSpan。 MHeap⽰意图: 2.MCache:运⾏时分配池,不针对全局,⽽是每个线程都有⾃⼰的局部内存缓存MCache,他是实现goroutine⾼并发的重要因素,因为分配 ⼩对象可直接从MCache中分配,不⽤加锁,提升了并发效率。 type MCache struct { tiny byte*; // Allocator cache for tiny objects w/o pointers. tinysize uintptr; alloc[NumSizeClasses] MSpan*; // spans to allocate from }; 尽可能将微⼩对象组合到⼀个tiny块中,提⾼性能。 alloc[]⽤于分配对象,如果没有了,则可以向对应的MCentral获取新的Span进⾏操作。 线程中分配⼩对象(16~32K)的过程: 对于 size 介于 16 ~ 32K byte 的内存分配先计算应该分配的 sizeclass,然后去 mcache ⾥⾯ alloc[sizeclass] 申请,如果 mcache.alloc[sizeclass] 不⾜以申请,则 mcache 向 mcentral 申请mcentral 给 mcache 分配完之后会判断⾃⼰需不需要扩充,如果需要则想 mheap 申请。 每个线程内申请内存是逐级向上的,⾸先看MCache是否有⾜够空间,没有就像MCentral申请,再没有就像MHea

文档评论(0)

166****9181 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档