第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

golang是自動(dòng)釋放內(nèi)存嗎?

golang是自動(dòng)釋放內(nèi)存嗎?

Go
Cats萌萌 2018-10-22 09:05:33
golang是自動(dòng)釋放內(nèi)存嗎
查看完整描述

1 回答

?
絕地?zé)o雙

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超4個(gè)贊

golang是一門自帶垃圾回收的語(yǔ)言,它的內(nèi)存分配器和tmalloc(thread-caching malloc)很像,大多數(shù)情況下是不需要用戶自己管理內(nèi)存的。最近了解了一下golang內(nèi)存管理,寫出來(lái)分享一下,不正確的地方請(qǐng)大佬們指出。

1.內(nèi)存池:

應(yīng)該有一個(gè)主要管理內(nèi)存分配的部分,向系統(tǒng)申請(qǐng)大塊內(nèi)存,然后進(jìn)行管理和分配。

2.垃圾回收:

當(dāng)分配的內(nèi)存使用完之后,不直接歸還給系統(tǒng),而是歸還給內(nèi)存池,方便進(jìn)行下一次復(fù)用。至于垃圾回收選擇標(biāo)記回收,還是分代回收算法應(yīng)該符合語(yǔ)言設(shè)計(jì)初衷吧。

3.大小切分:

使用單獨(dú)的數(shù)組或者鏈表,把需要申請(qǐng)的內(nèi)存大小向上取整,直接從這個(gè)數(shù)組或鏈表拿出對(duì)應(yīng)的大小內(nèi)存塊,方便分配內(nèi)存。大的對(duì)象以頁(yè)申請(qǐng)內(nèi)存,小的對(duì)象以塊來(lái)申請(qǐng),避免內(nèi)存碎片,提高內(nèi)存使用率。

4.多線程管理:

每個(gè)線程應(yīng)該有自己的內(nèi)存塊,這樣避免同時(shí)訪問(wèn)共享區(qū)的時(shí)候加鎖,提升語(yǔ)言的并發(fā)性,線程之間通信使用消息隊(duì)列的形式,一定不要使用共享內(nèi)存的方式。提供全局性的分配鏈,如果線程內(nèi)存不夠用了,可向分配鏈申請(qǐng)內(nèi)存。

這樣的內(nèi)存分配設(shè)計(jì)涵蓋了大部分語(yǔ)言的,上面的想法其實(shí)是把golang語(yǔ)言內(nèi)存分配抽象出來(lái)。其實(shí)Java語(yǔ)言也可以以同樣的方式理解。內(nèi)存池就是JVM堆,主要負(fù)責(zé)申請(qǐng)大塊內(nèi)存;多線程管理方面是使用棧內(nèi)存,每個(gè)線程有自己獨(dú)立的棧內(nèi)存進(jìn)行管理。

golang內(nèi)存分配器

golang內(nèi)存分配器主要包含三個(gè)數(shù)據(jù)結(jié)構(gòu):MHeap,MCentral以及MCache

1.MHeap:分配堆,主要是負(fù)責(zé)向系統(tǒng)申請(qǐng)大塊的內(nèi)存,為下層MCentral和MCache提供內(nèi)存服務(wù)。他管理的基本單位是MSpan(若干連續(xù)內(nèi)存頁(yè)的數(shù)據(jù)結(jié)構(gòu))

type MSpan struct

{

MSpan   *next;

MSpan   *prev;

PageId  start;  // 開(kāi)始的頁(yè)號(hào)

uintptr   npages; // 頁(yè)數(shù)

…..

};

可以看出MSpan是一個(gè)雙端鏈表的形式,里面存儲(chǔ)了它的一些位置信息。

通過(guò)一個(gè)基地址+(頁(yè)號(hào)*頁(yè)大小),就可以定位到這個(gè)MSpan的實(shí)際內(nèi)存空間。

type MHeap struct

{

lock  mutex;

free  [_MaxMHeapList] mSpanList  // free lists of given length

freelarge mSpanList   // free lists length >= _MaxMHeapList

busy  [_MaxMHeapList] mSpanList   // busy lists of large objects of given length

busylarge mSpanList

};

free數(shù)組以span為序號(hào)管理多個(gè)鏈表。當(dāng)central需要時(shí),只需從free找到頁(yè)數(shù)合適的鏈表。large鏈表用于保存所有超出free和busy頁(yè)數(shù)限制的MSpan。

MHeap示意圖:

2.MCache:運(yùn)行時(shí)分配池,不針對(duì)全局,而是每個(gè)線程都有自己的局部?jī)?nèi)存緩存MCache,他是實(shí)現(xiàn)goroutine高并發(fā)的重要因素,因?yàn)榉峙湫?duì)象可直接從MCache中分配,不用加鎖,提升了并發(fā)效率。

type MCache struct

{

tiny   byte*;  // Allocator cache for tiny objects w/o pointers.

tinysize   uintptr;

alloc[NumSizeClasses] MSpan*;  // spans to allocate from

};

盡可能將微小對(duì)象組合到一個(gè)tiny塊中,提高性能。

alloc[]用于分配對(duì)象,如果沒(méi)有了,則可以向?qū)?yīng)的MCentral獲取新的Span進(jìn)行操作。

線程中分配小對(duì)象(16~32K)的過(guò)程:

對(duì)于 size 介于 16 ~ 32K byte 的內(nèi)存分配先計(jì)算應(yīng)該分配的 sizeclass,然后去 mcache 里面 alloc[sizeclass] 申請(qǐng),如果 mcache.alloc[sizeclass] 不足以申請(qǐng),則 mcache 向 mcentral 申請(qǐng)mcentral 給 mcache 分配完之后會(huì)判斷自己需不需要擴(kuò)充,如果需要?jiǎng)t想 mheap 申請(qǐng)。

每個(gè)線程內(nèi)申請(qǐng)內(nèi)存是逐級(jí)向上的,首先看MCache是否有足夠空間,沒(méi)有就像MCentral申請(qǐng),再?zèng)]有就像MHeap,MHeap向系統(tǒng)申請(qǐng)內(nèi)存空間。

3.MCentral:作為MHeap和MCache的承上啟下的連接。承上,從MHeap申請(qǐng)MSpan;啟下,將MSpan劃分為各種尺寸的對(duì)象提供給MCache使用。

type MCentral struct

{

lock mutex;

sizeClass int32;

noempty mSpanList;

empty mSpanList;

int32 nfree;

……

};

type mSpanList struct {

first *mSpan

last  *mSpan

};

sizeclass: 也有成員 sizeclass,用于將MSpan進(jìn)行切分。

lock: 因?yàn)闀?huì)有多個(gè) P 過(guò)來(lái)競(jìng)爭(zhēng)。

nonempty: mspan 的雙向鏈表,當(dāng)前 mcentral 中可用的 mSpan list。

empty: 已經(jīng)被使用的,可以認(rèn)為是一種對(duì)所有 mSpan 的 track。MCentral存在于MHeap內(nèi)。

給對(duì)象 object 分配內(nèi)存的主要流程:

1.object size > 32K,則使用 mheap 直接分配。

2.object size < 16 byte,使用 mcache 的小對(duì)象分配器 tiny 直接分配。 (其實(shí) tiny 就是一個(gè)指針,暫且這么說(shuō)吧。)

3.object size > 16 byte && size <=32K byte 時(shí),先使用 mcache 中對(duì)應(yīng)的 size class 分配。

4.如果 mcache 對(duì)應(yīng)的 size class 的 span 已經(jīng)沒(méi)有可用的塊,則向 mcentral 請(qǐng)求。

5.如果 mcentral 也沒(méi)有可用的塊,則向 mheap 申請(qǐng),并切分。

6.如果 mheap 也沒(méi)有合適的 span,則想操作系統(tǒng)申請(qǐng)。

tcmalloc內(nèi)存分配器介紹

tcmalloc(thread-caching mallo)是google推出的一種內(nèi)存分配器。

具體策略:全局緩存堆和進(jìn)程的私有緩存。

1.對(duì)于一些小容量的內(nèi)存申請(qǐng)?jiān)囉眠M(jìn)程的私有緩存,私有緩存不足的時(shí)候可以再?gòu)娜志彺嫔暾?qǐng)一部分作為私有緩存。

2.對(duì)于大容量的內(nèi)存申請(qǐng)則需要從全局緩存中進(jìn)行申請(qǐng)。而大小容量的邊界就是32k。緩存的組織方式是一個(gè)單鏈表數(shù)組,數(shù)組的每個(gè)元素是一個(gè)單鏈表,鏈表中的每個(gè)元素具有相同的大小。

golang語(yǔ)言中MHeap就是全局緩存堆,MCache作為線程私有緩存。

在文章開(kāi)頭說(shuō)過(guò),內(nèi)存池就是利用MHeap實(shí)現(xiàn),大小切分則是在申請(qǐng)內(nèi)存的時(shí)候就做了,同時(shí)MCache分配內(nèi)存時(shí),可以用MCentral去取對(duì)應(yīng)的sizeClass,多線程管理方面則是通過(guò)MCache去實(shí)現(xiàn)。

總結(jié):

1.MHeap是一個(gè)全局變量,負(fù)責(zé)向系統(tǒng)申請(qǐng)內(nèi)存,mallocinit()函數(shù)進(jìn)行初始化。如果分配內(nèi)存對(duì)象大于32K直接向MHeap申請(qǐng)。

2.MCache線程級(jí)別管理內(nèi)存池,關(guān)聯(lián)結(jié)構(gòu)體P,主要是負(fù)責(zé)線程內(nèi)部?jī)?nèi)存申請(qǐng)。

3.MCentral連接MHeap與MCache的,MCache內(nèi)存不夠則向MCentral申請(qǐng),MCentral不夠時(shí)向MHeap申請(qǐng)內(nèi)存。



查看完整回答
反對(duì) 回復(fù) 2018-11-15
  • 1 回答
  • 0 關(guān)注
  • 2293 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)