導航:首頁 > 源碼編譯 > golang演算法圖

golang演算法圖

發布時間:2025-06-06 03:45:59

❶ golang gc介紹

Go語言的垃圾回收機制介紹如下

總結:Go語言的垃圾回收機制通過不斷優化和改進,有效提升了程序性能和穩定性,減輕了開發者對內存管理的負擔,避免了內存泄漏等問題。

❷ golang是自動釋放內存嗎

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

1.內存池:

應該有一個主要管理內存分配的部分,向系統申請大塊內存,然後進行管理和分配。

2.垃圾回收:

當分配的內存使用完之後,不直接歸還給系統,而是歸還給內存池,方便進行下一次復用。至於垃圾回收選擇標記回收,還是分代回收演算法應該符合語言設計初衷吧。

3.大小切分:

使用單獨的數組或者鏈表,把需要申請的內存大小向上取整,直接從這個數組或鏈表拿出對應的大小內存塊,方便分配內存。大的對象以頁申請內存,小的對象以塊來申請,避免內存碎片,提高內存使用率。

4.多線程管理:

每個線程應該有自己的內存塊,這樣避免同時訪問共享區的時候加鎖,提升語言的並發性,線程之間通信使用消息隊列的形式,一定不要使用共享內存的方式。提供全局性的分配鏈,如果線程內存不夠用了,可向分配鏈申請內存。

這樣的內存分配設計涵蓋了大部分語言的,上面的想法其實是把golang語言內存分配抽象出來。其實Java語言也可以以同樣的方式理解。內存池就是JVM堆,主要負責申請大塊內存;多線程管理方面是使用棧內存,每個線程有自己獨立的棧內存進行管理。

golang內存分配器

golang內存分配器主要包含三個數據結構:MHeap,MCentral以及MCache

1.MHeap:分配堆,主要是負責向系統申請大塊的內存,為下層MCentral和MCache提供內存服務。他管理的基本單位是MSpan(若干連續內存頁的數據結構)

type MSpan struct

{

MSpan *next;

MSpan *prev;

PageId start; // 開始的頁號

uintptr npages; // 頁數

…..

};

可以看出MSpan是一個雙端鏈表的形式,裡面存儲了它的一些位置信息。

通過一個基地址+(頁號*頁大小),就可以定位到這個MSpan的實際內存空間。

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數組以span為序號管理多個鏈表。當central需要時,只需從free找到頁數合適的鏈表。large鏈表用於保存所有超出free和busy頁數限制的MSpan。

MHeap示意圖:

2.MCache:運行時分配池,不針對全局,而是每個線程都有自己的局部內存緩存MCache,他是實現goroutine高並發的重要因素,因為分配小對象可直接從MCache中分配,不用加鎖,提升了並發效率。

type MCache struct

{

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

tinysize uintptr;

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

};

盡可能將微小對象組合到一個tiny塊中,提高性能。

alloc[]用於分配對象,如果沒有了,則可以向對應的MCentral獲取新的Span進行操作。

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

對於
size 介於 16 ~ 32K byte 的內存分配先計算應該分配的 sizeclass,然後去 mcache 裡面
alloc[sizeclass] 申請,如果 mcache.alloc[sizeclass] 不足以申請,則 mcache 向 mcentral
申請mcentral 給 mcache 分配完之後會判斷自己需不需要擴充,如果需要則想 mheap 申請。

每個線程內申請內存是逐級向上的,首先看MCache是否有足夠空間,沒有就像MCentral申請,再沒有就像MHeap,MHeap向系統申請內存空間。

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

type MCentral struct

{

lock mutex;

sizeClass int32;

noempty mSpanList;

empty mSpanList;

int32 nfree;

……

};

type mSpanList struct {

first *mSpan

last *mSpan

};

sizeclass: 也有成員 sizeclass,用於將MSpan進行切分。

lock: 因為會有多個 P 過來競爭。

nonempty: mspan 的雙向鏈表,當前 mcentral 中可用的 mSpan list。

empty: 已經被使用的,可以認為是一種對所有 mSpan 的 track。MCentral存在於MHeap內。

給對象 object 分配內存的主要流程:

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

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

3.object size > 16 byte && size <=32K byte 時,先使用 mcache 中對應的 size class 分配。

4.如果 mcache 對應的 size class 的 span 已經沒有可用的塊,則向 mcentral 請求。

5.如果 mcentral 也沒有可用的塊,則向 mheap 申請,並切分。

6.如果 mheap 也沒有合適的 span,則想操作系統申請。

tcmalloc內存分配器介紹

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

具體策略:全局緩存堆和進程的私有緩存。

1.對於一些小容量的內存申請試用進程的私有緩存,私有緩存不足的時候可以再從全局緩存申請一部分作為私有緩存。

2.對於大容量的內存申請則需要從全局緩存中進行申請。而大小容量的邊界就是32k。緩存的組織方式是一個單鏈表數組,數組的每個元素是一個單鏈表,鏈表中的每個元素具有相同的大小。

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

在文章開頭說過,內存池就是利用MHeap實現,大小切分則是在申請內存的時候就做了,同時MCache分配內存時,可以用MCentral去取對應的sizeClass,多線程管理方面則是通過MCache去實現。

總結:

1.MHeap是一個全局變數,負責向系統申請內存,mallocinit()函數進行初始化。如果分配內存對象大於32K直接向MHeap申請。

2.MCache線程級別管理內存池,關聯結構體P,主要是負責線程內部內存申請。

3.MCentral連接MHeap與MCache的,MCache內存不夠則向MCentral申請,MCentral不夠時向MHeap申請內存。

閱讀全文

與golang演算法圖相關的資料

熱點內容
伺服器路由表怎麼用 瀏覽:965
php內置函數源碼 瀏覽:846
資金回頭選股源碼 瀏覽:252
dz宏命令 瀏覽:353
蟻群演算法實現一維優化代碼 瀏覽:319
伺服器釋放有什麼用 瀏覽:390
解壓包子洗了變粘了怎麼辦 瀏覽:830
635除以三十的簡便演算法 瀏覽:638
樂高ev3編程軟體安卓 瀏覽:337
u盤加密軟體費用 瀏覽:263
中國程序員年死亡率 瀏覽:840
尚德app發帖從哪裡刪除 瀏覽:801
哪裡有學中國象棋的app 瀏覽:115
虛擬機如何編譯bin 瀏覽:832
文件夾藍屏是怎麼回事 瀏覽:641
奧特佳壓縮機日產軒逸 瀏覽:581
隨申辦app在哪裡下載 瀏覽:879
哪裡下載千圖app 瀏覽:724
php打碼嵌入html文檔 瀏覽:461
java如何彈出文件夾選擇框選擇文件路徑 瀏覽:539