内存分配原理

一、基本情况

  1. 内存分配器有glibc提供的ptmalloc2,谷歌提供的tcmalloc,脸书提供的jemalloc
  2. golang中提供了内存分配器,原理与tcmalloc类似,简单说维护一块大的全局内存,每个线程维护一块小的私有内存,私有内存不足再从全局申请
  3. 内存分配与GC(垃圾回收)有密切关系,所以,了解GC前需要了解内存分配的原理

二、基本概念

  1. 为了golang自主管理内存,先向系统申请一块内存,然后将内存切割成小块,通过一定的内存分配算法管理内存。img
  2. 申请的内存划分为三个部分,spans,bitmap,arena.其中arena为堆区,程序中需要的内存从这里分配。
  3. spans,bitmap为了管理arena而存在。arena大小为512G,为了管理arena区域,区域划分成一个个page,每个page 8k,共512G/8k
  4. spans 区域存放span指针,每个指针对应一个或多个page,所以span区域的大小为 512G/8k指针大小8byte=512M
  5. bitmap区域大小通过arena计算出来,一般用于GC垃圾回收

三、 span

// class  bytes/obj  bytes/span  objects  waste bytes
//     1          8        8192     1024            0
//     2         16        8192      512            0
//     3         32        8192      256            0
//     4         48        8192      170           32
//     5         64        8192      128            0
//     6         80        8192      102           32
//     7         96        8192       85           32
//     8        112        8192       73           16
//     9        128        8192       64            0
//    10        144        8192       56          128
//    11        160        8192       51           32
//    12        176        8192       46           96
//    13        192        8192       42          128
//    14        208        8192       39           80
//    15        224        8192       36          128
//    16        240        8192       34           32
//    17        256        8192       32            0
//    18        288        8192       28          128
//    19        320        8192       25          192
//    20        352        8192       23           96
//    21        384        8192       21          128
//    22        416        8192       19          288
//    23        448        8192       18          128
//    24        480        8192       17           32
//    25        512        8192       16            0
//    26        576        8192       14          128
//    27        640        8192       12          512
//    28        704        8192       11          448
//    29        768        8192       10          512
//    30        896        8192        9          128
//    31       1024        8192        8            0
//    32       1152        8192        7          128
//    33       1280        8192        6          512
//    34       1408       16384       11          896
//    35       1536        8192        5          512
//    36       1792       16384        9          256
//    37       2048        8192        4            0
//    38       2304       16384        7          256
//    39       2688        8192        3          128
//    40       3072       24576        8            0
//    41       3200       16384        5          384
//    42       3456       24576        7          384
//    43       4096        8192        2            0
//    44       4864       24576        5          256
//    45       5376       16384        3          256
//    46       6144       24576        4            0
//    47       6528       32768        5          128
//    48       6784       40960        6          256
//    49       6912       49152        7          768
//    50       8192        8192        1            0
//    51       9472       57344        6          512
//    52       9728       49152        5          512
//    53      10240       40960        4            0
//    54      10880       32768        3          128
//    55      12288       24576        2            0
//    56      13568       40960        3          256
//    57      14336       57344        4            0
//    58      16384       16384        1            0
//    59      18432       73728        4            0
//    60      19072       57344        3          128
//    61      20480       40960        2            0
//    62      21760       65536        3          256
//    63      24576       24576        1            0
//    64      27264       81920        3          128
//    65      28672       57344        2            0
//    66      32768       32768        1            0
type mspan struct {
		next       *mspan    //链表后向指针,用于将span链接起来
		prev       *mspan    //链表前向指针,用于将span链接起来
		startAddr  uintptr   //起始地址,也即所管理页的地址
		npages     uintptr   //管理的页数
		nelems     uintptr   //块个数,也即有多少个块可供分配
		allocBits  *gcBits   //分配位图,每一位代表一个块是否已分配
		allocCount uint16    //已分配块的个数
		spanclass  spanClass //class表中的class ID
		elemsize   uintptr   //class表中的对象大小,也即块大小
}
type mcache struct {
    alloc [67*2]*mspan // 按class分组的mspan列表
}
type mcentral struct {
    lock      mutex     //互斥锁
    spanclass spanClass // span class ID
    nonempty  mSpanList // non-empty 指还有空闲块的span列表
    empty     mSpanList // 指没有空闲块的span列表

    nmalloc uint64      // 已累计分配的对象个数
}
type mheap struct {
    lock      mutex

    spans []*mspan

    bitmap        uintptr     //指向bitmap首地址,bitmap是从高地址向低地址增长的

    arena_start uintptr        //指示arena区首地址
    arena_used  uintptr        //指示arena区已使用地址位置

    central [67*2]struct {
        mcentral mcentral
        pad      [sys.CacheLineSize - unsafe.Sizeof(mcentral{})%sys.CacheLineSize]byte
    }
}