golang做爲一種「高級語言」,也提供了本身的內存管理機制。這樣一方面能夠簡化編碼的流程,下降因內存使用致使出現問題的頻率(C語言使用者尤爲是初學者應該深有體會),對程序猿友好。另外一方面也能夠減小內存相關係統調用,提高性能。golang
先了解下內存管理大體策略:併發
如下,基於go1.9版本,看下golang內存分配實現的基本思路。高併發
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。spa
go內存分配主要有三個管理組件:操作系統
mcachecode
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對象爲例,看一下內存申請流程:
計算對象大小,按預約義的sizeclass表(見下)從私有的mcache中找到對應規格的mspan。好比大小爲112 byte的對象,對應8192 byte大小的mspan。而後經過mspan的空閒bitmap查找空閒的塊,若是空閒塊存在,分配完成。
以上是mcache內的分配操做,不須要加鎖。
若是mspan沒有空閒塊,則向mcentral申請對應大小的空閒mspan。好比112 byte的對象,須要向mcentral申請8192 byte大小的空閒mspan。
因爲申請獲取全局的mspan,須要在mcentral級別加鎖。
若是mcentral中沒有空閒mspan,則向mheap申請,並劃分object。
若是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
參考文獻: