基本分配单元 class和span

go内存管理粒度是8KB(在大多数操作系统中,一个page大小为4KB,对于go来说,也就是两个page),可以理解为在go中page是8KB大小,每次go分配一个page就是分配8KB内存

go对象管理粒度分为67种大小,也叫class或者块

一个page根据class大小可以分为 8K/class size, 如果class为1K,那么可以分8个

class相同且地址连续的pages组成一个span(逻辑上,实际没有这个struct)

class相同但不连续span使用mspan管理,mspan之间组成双端队列关联起来

span: class相同,多个连续pages;mspan是span节点的实际struct,mspan组成双端队列

四种主要的管理结构

mspan

每个mspan的class是相同的,多个mspan组成一个双端队列

其中mSpanList是双端队列的head

mspan是以下三种数据结构管理的单元,mcache、mcentral、mheap都直接管理mspan,三者之间没有严格的包含关系,只是用于不同的目的来共同配合管理所有mspan

type mspan struct {next *mspan     // next span in list, or nil if noneprev *mspan     // previous span in list, or nil if nonelist *mSpanList // For debugging. TODO: Remove.startAddr uintptr // address of first byte of span aka s.base()npages    uintptr // number of pages in span...
}

mcache

每个mcache包含所有的class类型(<=32KB)的mspan

每个mcache对于同一种clas都包含scan和noscan两种mspan队列,其中scan含有指针对象

每个线程(P)有各自的mcache,无需加锁访问

type mcache struct {// The following members are accessed on every malloc,// so they are grouped here for better caching.next_sample uintptr // trigger heap sample after allocating this many byteslocal_scan  uintptr // bytes of scannable heap allocated// Allocator cache for tiny objects w/o pointers.// See "Tiny allocator" comment in malloc.go.// tiny points to the beginning of the current tiny block, or// nil if there is no current tiny block.//// tiny is a heap pointer. Since mcache is in non-GC'd memory,// we handle it by clearing it in releaseAll during mark// termination.tiny             uintptrtinyoffset       uintptrlocal_tinyallocs uintptr // number of tiny allocs not counted in other stats// The rest is not accessed on every malloc.alloc [numSpanClasses]*mspan // spans to allocate from, indexed by spanClass...
}

mcentral

每个mcentral只针对特定的一种class,但mcentral包含的是两个mspan双端队列,分别代表空队列和非空队列

所有线程共享,需要加锁访问,但每次只对一种class的mcentral加锁

type mcentral struct {lock      mutexspanclass spanClassnonempty  mSpanList // list of spans with a free object, ie a nonempty free listempty     mSpanList // list of spans with no free objects (or cached in an mcache)// nmalloc is the cumulative count of objects allocated from// this mcentral, assuming all spans in mcaches are// fully-allocated. Written atomically, read under STW.nmalloc uint64
}

mheap

包含所有不同class的mcentral和所有的mspan

并且当分配的对象大于32KB时,直接从mheap分配

所有线程共享,需要加锁访问

type mheap struct {// lock must only be acquired on the system stack, otherwise a g// could self-deadlock if its stack grows with the lock held.lock      mutexpages     pageAlloc // page allocation data structuresweepgen  uint32    // sweep generation, see comment in mspan; written during STWsweepdone uint32    // all spans are sweptsweepers  uint32    // number of active sweepone calls// allspans is a slice of all mspans ever created. Each mspan// appears exactly once.//// The memory for allspans is manually managed and can be// reallocated and move as the heap grows.//// In general, allspans is protected by mheap_.lock, which// prevents concurrent access as well as freeing the backing// store. Accesses during STW might not hold the lock, but// must ensure that allocation cannot happen around the// access (since that may free the backing store).allspans []*mspan // all spans out there...// central free lists for small size classes.// the padding makes sure that the mcentrals are// spaced CacheLinePadSize bytes apart, so that each mcentral.lock// gets its own cache line.// central is indexed by spanClass.central [numSpanClasses]struct {mcentral mcentralpad      [cpu.CacheLinePadSize - unsafe.Sizeof(mcentral{})%cpu.CacheLinePadSize]byte}spanalloc             fixalloc // allocator for span*cachealloc            fixalloc // allocator for mcache*specialfinalizeralloc fixalloc // allocator for specialfinalizer*specialprofilealloc   fixalloc // allocator for specialprofile*speciallock           mutex    // lock for special record allocators.arenaHintAlloc        fixalloc // allocator for arenaHintsunused *specialfinalizer // never set, just here to force the specialfinalizer type into DWARF
}

整体关系图

分配原则

  • 大于 32K 的大对象直接从 mheap 分配。
  • 小于 16B 的使用 mcache 的微型分配器分配
  • 对象大小在 16B ~ 32K 之间的的,首先通过计算使用的大小规格,然后使用 mcache 中对应大小规格的块分配
  • 如果对应的大小规格在 mcache 中没有可用的块,则向 mcentral 申请
  • 如果 mcentral 中没有可用的块,则向 mheap 申请,并根据 BestFit 算法找到最合适的 mspan。如果申请到的 mspan 超出申请大小,将会根据需求进行切分,以返回用户所需的页数。剩余的页构成一个新的 mspan 放回 mheap 的空闲列表。
  • 如果 mheap 中没有可用 span,则向操作系统申请一系列新的页(最小 1MB)。

参考

https://blog.learngoprogramming.com/a-visual-guide-to-golang-memory-allocator-from-ground-up-e132258453ed​blog.learngoprogramming.comGo Memory Management - Povilas Versockas​povilasv.me

https://golang.org/src/runtime/mheap.go​golang.orghttps://golang.org/src/runtime/mcache.go​golang.orghttps://golang.org/src/runtime/mcentral.go​golang.org

内存分配_go内存分配管理相关推荐

  1. multiprocessing.manager管理的对象需要加锁吗_Go: 内存管理和分配

    本文基于Go1.13 当不再使用内存时,标准库会自动执行Go的内存管理即从分配到回收.尽管开发者不需要处理它,但是Go的底层管理进行了很好的优化并且充满了有趣的概念. 堆上的分配 内存管理被设计可以在 ...

  2. 11 操作系统第三章 内存管理 内存的基本知识 内存管理 内存空间扩充 连续分配管理方式

    文章目录 1 内存概念 1.1 内存作用 1.2 逻辑地址VS物理地址 1.3 装入的三种方式 1.3.1 绝对装入 1.3.2 可重定位装入 1.3.3 动态重定位装入 1.4 链接的三种方式 1. ...

  3. alloc_page分配内存空间--Linux内存管理(十七)

    1 前景回顾 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Know ...

  4. 【Linux 内核 内存管理】Linux 内核内存布局 ③ ( Linux 内核 动态分配内存 系统接口函数 | 统计输出 vmalloc 分配的内存 )

    文章目录 一.Linux 内核 动态分配内存 系统接口函数 二.统计输出 vmalloc 分配的内存 一.Linux 内核 动态分配内存 系统接口函数 Linux 内核 " 动态分配内存 & ...

  5. java 内存分配管理_JAVA实验操作系统内存管理-最优分配,最先分配,最坏分配算法...

    package Memory; import java.util.ArrayList; import java.util.Iterator; import java.util.Scanner; pub ...

  6. 栈和堆存储在计算机RAM中,堆内存和栈内存及C++内存分配

    1.现代操作系统内存管理主流的操作系统(Windows,Linux)都采用虚拟内存管理的方式,具体说就是:页式管理.段式管理.段页式管理. 操作系统分配资源的单位是进程,所以,内存管理的过程也是以进程 ...

  7. c 和java 内存,C分配和内存开销

    可能会让年轻的开发人员感到惊讶,因为像我这样老的老用户曾经用1或2k RAM的系统用C语言编写 . 在这种规模的系统中,动态内存分配将是我们无法承受的奢侈品 . 它不仅仅是管理免费存储的指针开销,还有 ...

  8. JVM自动化的内存分配与内存回收

    如何区分一个C++程序员和Java程序员?答案是看他吃饭完收不收拾碗筷,反正我是不收拾,哈哈哈哈哈哈. Java技术体系中所提倡的自动内存管理最终可以归结为自动化地解决了两个问题:给对象分配内存以及回 ...

  9. JVM之JVM内存区域与内存分配(转载)

    2019独角兽企业重金招聘Python工程师标准>>> 先来看看JVM运行时候的内存区域 大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区),He ...

最新文章

  1. 共识算法的比较:Casper vs Tendermint
  2. 数据结构-单链表(C语言代码)
  3. 如何避免云整合的问题
  4. 基于模板的通用代码生成器LKGenerator(三)-模板示例
  5. 表-创建表-表的转换函数
  6. 实战JavaScript:实现贪吃蛇——面向对象练习
  7. 【热聘】蚂蚁金服-系统软件和安全资深/高级/专家/工程师
  8. 带自动定位的水印相机_水印相机自动定位应该如何设置
  9. 人件管理与中国古代史:程序员豫让
  10. matlab求解全微分函数,Matlab求解一元函数,再求全微分的错误,表达式复杂不会........
  11. 解锁图案-九宫格有多少种组合?安全吗?用程序来解答
  12. C++——输入、输出和文件
  13. 基于Domoticz智能家居系统(十四)用ESP8266做MQTT客户端实验
  14. 使用Git Bash的scp复制文件到Linux
  15. java中使用length获取二维数组的长度
  16. 制作Wi-Fi Ducky远程HID攻击设备
  17. 手机号,邮箱正则匹配验证
  18. A Pulmonary Nodule Detection Model Based on Progressive Resolution and Hierarchical Saliency
  19. 如何测试代理IP的质量?
  20. Qt配置项目编码格式

热门文章

  1. html5图片加载不了,webView加载html图片遇到的问题解决
  2. java filesystem 追加_java 如何往已经存在的excel表格里面追加数据的方法
  3. Python Numba CPU下加速
  4. pip 查看安装路径
  5. error: failed linking file resources
  6. Re-ID新方法VPM
  7. opencv 运动检测
  8. pycharm Application cannot start in headless mode
  9. 数据处理——One-Hot Encoding
  10. 【Python排序搜索基本算法】之拓扑排序