記憶體分配 Go記憶體管理 記憶體分配一

2021-10-25 13:12:07 字數 1688 閱讀 2801

go作為乙個比較新晚(新)的語言,自然借鑑前輩們的優點,比如說語言本身負責記憶體管理、對協程和高併發的高優支援、簡單高效的語法等。本篇及後續的幾篇要講的就是還沒提到的比較複雜的記憶體管理。 學習記憶體管理(分配&**)前,如果有jvm的記憶體管理的基礎,會變得非常簡單,如果是第一次接觸記憶體管理,在看完go的記憶體管理後可以去看看jvm的,對比著學習比較容易理解。 go的記憶體管理思路是基於google 的tcmalloc(thread-caching-malloc)實現的,常見的記憶體分配器還有ptmalloc、jemalloc,但是tcmalloc的效能更高,尤其是高併發場景下。

tcmalloc的分配的記憶體主要**於:全域性快取堆程序私有快取,小容量的記憶體申請使用私有快取,如果私有快取不夠,則從全域性快取堆中申請一部分作為私有快取。大物件會直接從全域性快取中申請,至於大小的分界是32k。

小物件記憶體分配缺省會分配86個不同大小的塊,這些塊的大小不一致,內部採用單鏈表陣列來組織記憶體,使用時遵循懶載入策略,等到使用時才進行初始化。

大於32k的記憶體申請,屬於大物件的分配,使用全域性快取堆直接分配,記憶體的組織方式也是通過單鏈表陣列進行的,資料長度是256,每個鍊錶的元素的大小是不同的,但都是4k(1page)的整數倍。

tcmalloc使用span來管理記憶體分頁,乙個span可以包含幾個連續分頁。span的狀態只有未分配、作為大物件分配、作為小物件分配。

1、申請一塊較大的虛擬記憶體空間,用於記憶體分配及管理 當空間不足時,向系統申請一塊較大的記憶體,如100kb或者1mb 申請到的記憶體塊按特定的size,被分割成多種小塊記憶體(go:_numsizeclasses = 67),並用鍊錶管理。建立物件時,按照物件大小,從空閒鍊錶中查詢到最適合的記憶體塊。 2、銷毀物件時,將對應的記憶體塊返還空閒鍊錶中以復用。 3、空閒記憶體達到最大值時,返還作業系統。

go將記憶體分為三個層級,協程私有記憶體,全域性記憶體,整體記憶體葉管理,也因此有這三個層級的記憶體管理工具。

mspan:mspan並不直接擁有記憶體空間,它負責管理起始位址為startaddr、級別(預分配頁的個數)為sizeclass的連續位址空間。mcache:per-p私有cache,用於實現無鎖的object分配,每個mcache有大小為67的mspan陣列,儲存不同級別大小的mspan。mcentral:全域性記憶體,為各個cache提供按大小劃分好的mspan,mcentral有個關鍵方法cachespan(),它是整個分配的核心演算法mheap是真實擁有虛擬位址的結構,page管理,記憶體不足時向系統申請。 總體來說,他們之間的關係是這樣的: golang程式啟動時申請一大塊記憶體,並劃分成spans、bitmap、arena區域,arena區域按頁劃分成乙個個小塊,span管理乙個或多個頁,mcentral管理多個span供執行緒申請使用,mcache作為執行緒私有資源,資源**於mcentral。 本篇暫時就介紹這麼多。

go 記憶體分配

二者都是在堆上分配記憶體,但是它們的行為不同,適用於不同的型別 new 函式分配記憶體,make 函式初始化 new t 為型別t分配一塊記憶體,並返回指向這塊記憶體位址的指標,它適用於值型別如陣列和結構體 make t 初始化內建的資料結構,返回乙個型別為 t 的空值,它只適用於3種內建的引用型別...

記憶體分配管理

系統中的記憶體分為棧 堆 全域性區 區 棧 由編譯器自動分配釋放,參訪函式的引數值,區域性變數,函式棧幀,函式呼叫過程。堆 由程式設計師自行分配想要的空間大小,c中的malloc等函式,c 中的new 全域性區 資料區 存放的是全域性變數和靜態變數,初始化的存在一起,未初始化的放一起,程式結束後由系...

C 記憶體管理 記憶體分配

1 c 編譯的程式占用的記憶體分類 1 棧區 stack 程式執行時由編譯器自動分配,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。程式結束時由編譯器自動釋放。2 堆區 heap 在記憶體開闢另一塊儲存區域。一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os 注...