zoukankan      html  css  js  c++  java
  • Go语言内存管理(一)内存分配

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

    golang作为一种“高级语言”,也提供了自己的内存管理机制。这样一方面可以简化编码的流程,降低因内存使用导致出现问题的频率(C语言使用者尤其是初学者应该深有体会),对程序猿友好。另一方面也可以减少内存相关系统调用,提升性能。

    先了解下内存管理大致策略:

    • 申请一块较大的地址空间(虚拟内存),用于内存分配及管理(golang:spans+bitmap+arena->512M+16G+512G)
    • 当空间不足时,向系统申请一块较大的内存,如100KB或者1MB
    • 申请到的内存块按特定的size,被分割成多种小块内存(golang:_NumSizeClasses = 67),并用链表管理起来
    • 创建对象时,按照对象大小,从空闲链表中查找到最适合的内存块
    • 销毁对象时,将对应的内存块返还空闲链表中以复用
    • 空闲内存达到阈值时,返还操作系统

    以下,基于go1.9版本,看下golang内存分配实现的基本思路。

    Go内存管理的实现

    go的内存管理实现基于TCMalloc(Thread-Caching Malloc)。

    TCMalloc是 Google 开发的多级内存分配器,具有对抗内存碎片化,适合高并发场景的特性。据称,它的内存分配速度是 glibc2.3 中实现的 malloc的数倍。

    和TCMalloc相同,go的内存分配也是基于两种粒度的内存单位:span和object。span是连续的page,按page的数量进行归类,比如分为2个page的span,4个page的span等。object是span中按预设大小划分的块,也是按大小分类。同一个span中,只有一种类型(大小)的object。

    go内存分配主要有三个管理组件:

    • mcache

      Per-P(Processer,具体参见go中G,M,P的概念)私有cache,用于实现无锁的object分配

    • mcentral

      全局内存,为各个cache提供按大小划分好的span

    • mheap

      全局内存,page管理,内存不足时向系统申请

    通过将内存分配流程分为三个层级,既能保证Processer级别(mcache)的无锁分配,又能在mcentral级别实现内存全局共享,避免浪费。

    go将内存申请按大小分为三种类型:tiny,small,large。tiny是小于16个byte的申请,small是小于32KB的申请,大于32KB为large,三种类型的处理方式有所不同。

    _TinySize      = 16
    _MaxSmallSize   = 32768
    

    我们以一个small对象为例,看一下内存申请流程:

    1. 计算对象大小,按预定义的sizeclass表(见下)从私有的mcache中找到对应规格的mspan。比如大小为112 byte的对象,对应8192 byte大小的mspan。然后通过mspan的空闲bitmap查找空闲的块,如果空闲块存在,分配完成。

      以上是mcache内的分配操作,不需要加锁。

    2. 如果mspan没有空闲块,则向mcentral申请对应大小的空闲mspan。比如112 byte的对象,需要向mcentral申请8192 byte大小的空闲mspan。

      由于申请获取全局的mspan,需要在mcentral级别加锁。

    3. 如果mcentral中没有空闲mspan,则向mheap申请,并划分object。

    4. 如果mheap没有足够的空闲page,则向操作系统申请不少于1M的page。

    以上就是small对象的内存分配流程。

    large对象的申请,跳过了mcache和mcentral,直接从mheap中分配。

    对于tiny对象的申请,mcache中有专门的内存区域“tiny”来进行特殊处理。“tiny”将对象按大小与tinyoffset(“tiny”当前分配地址)对齐,然后分配,并记录下新的tinyoffset,用于下次分配。如果空间不足,则另外申请16 byte的内存块。

    // sizeclass
    // 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
    

    参考文献:

    TCMalloc

    图解 TCMalloc

  • 相关阅读:
    PHP 对Memcache的使用实例
    PHP Memcache 扩展安装
    Effective STL 读书笔记
    windows下安装和使用scrapy
    使用insert ignore来避免向数据库重复插入数据
    2017年末
    归并排序
    二叉树的中序遍历
    正则表达式
    tinymq学习小结
  • 原文地址:https://www.cnblogs.com/ldaniel/p/8502867.html
Copyright © 2011-2022 走看看