go內(nèi)存管理-內(nèi)存分配-學(xué)習(xí)心得
今天想分享下自己學(xué)習(xí)go內(nèi)存分配的一些心得。
首先,go程序啟動(dòng)時(shí)需要向系統(tǒng)申請(qǐng)內(nèi)存資源。內(nèi)容包含三個(gè)部分

spans:指針,指向arena的指針
bitmap:垃圾回收使用
arena:真正的存儲(chǔ)空間
這個(gè)概念大概了解即可。
go的內(nèi)存管理采用的是分級(jí)管理從cache->central->heap并且采用分類分配,將對(duì)象分為0-66共67類。
通過(guò)內(nèi)存管理單位mspan來(lái)進(jìn)行管理,將內(nèi)存分頁(yè),每頁(yè)8K。
每個(gè)協(xié)程有自己的cache,當(dāng)cache不夠用的時(shí)候向cental申請(qǐng),central不夠向heap申請(qǐng),heap不夠向內(nèi)存申請(qǐng)。
mcache里持有67*2個(gè)類型的mspan。每個(gè)類型的分兩種。一種是需要掃描的即帶指針的,一種是不需要掃描即不帶指針的。主要是為了垃圾回收方便。
mheap持有67*2個(gè)類型的mcentral。每個(gè)類型也分兩種。一個(gè)是需要掃描的,一種是不需要掃描的。
當(dāng)某個(gè)類型的mspan不夠用了,就向?qū)?yīng)類型的mcentral申請(qǐng)資源。
mcentral有兩個(gè)鏈表,一個(gè)是empty已經(jīng)申請(qǐng)的空間,一個(gè)是noempty空閑的可以申請(qǐng)的空間。
申請(qǐng)時(shí)需要加鎖,因?yàn)槭侨仲Y源,避免競(jìng)爭(zhēng)。然后mcentral將從noempty中分配mspan,將其加入到empty中。返回并解鎖。
回收的時(shí)候也一樣,先加鎖。然后將內(nèi)存從empty中刪除,加入到noempty中,然后解鎖。
基本就是這么一個(gè)過(guò)程了。
分配的時(shí)候,如果小于16B并且不包含指針,使用tiny分配。16B到32K的正常分配。大于32K的有mheap分配。
以申請(qǐng)size為n的內(nèi)存為例,分配步驟如下:
獲取當(dāng)前線程的私有緩存mcache
跟據(jù)size計(jì)算出適合的class的ID
從mcache的alloc[class]鏈表中查詢可用的span
如果mcache沒(méi)有可用的span則從mcentral申請(qǐng)一個(gè)新的span加入mcache中
如果mcentral中也沒(méi)有可用的span則從mheap中申請(qǐng)一個(gè)新的span加入mcentral
從該span中獲取到空閑對(duì)象地址并返回
歡迎和諧討論
參考自go專家編程
第四章:內(nèi)存管理 - 4.1 內(nèi)存分配原理 - 《GO專家編程》 - 書(shū)棧網(wǎng) · BookStack