您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“go內(nèi)存是怎么分配的”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“go內(nèi)存是怎么分配的”吧!
程序中的數(shù)據(jù)和變量會被分配到程序的虛擬內(nèi)存中,內(nèi)存空間包含兩個重要的區(qū)域:堆(Heap)和棧(Stack)。函數(shù)調(diào)用的參數(shù)、返回值以及局部變量大都會被分配到棧上,這部分內(nèi)存會由編譯器進(jìn)行管理。不同的語言使用不同的方法管理堆區(qū)內(nèi)存,c語言中,需要主動申請和釋放內(nèi)存,在java中和go中基本上都交由編譯器管理,堆中的對象由內(nèi)存分配器分配以及垃圾回收器
內(nèi)存管理一般包含三個不同的組件,分別是Mutator(用戶程序)、Allocator(分配器)、Collector(收集器)。當(dāng)用戶程序申請內(nèi)存時,會通過內(nèi)存分配器申請新內(nèi)存,而分配器會負(fù)責(zé)從堆中初始化相應(yīng)的內(nèi)存區(qū)域。
內(nèi)存分配器一般包含兩種分配方法
這是一種高效的內(nèi)存分配方法,但是局限性比較大。只需要在內(nèi)存中維護(hù)一個指向內(nèi)存特定位置的指針,如果申請內(nèi)存,分配器只需要檢查剩余的空閑內(nèi)存、返回分配的內(nèi)存區(qū)域并修改指針在內(nèi)存中的位置。
雖然這種方式擁有較快的執(zhí)行速度以及角度的實現(xiàn)復(fù)雜度,但是無法在內(nèi)存被釋放時重用內(nèi)存。
通常情況下需要與合適的垃圾回收算法配合使用,例如 標(biāo)記壓縮(Mark-Compact)、復(fù)制回收(Copying GC)和分代回收(Generational GC)等算法。它們可以通過拷貝的方式整理存活對象的碎片,定期合并空閑內(nèi)存,提升分配器的性能
這種方法可以重用已經(jīng)被釋放的內(nèi)存,它在內(nèi)部維護(hù)一個類似鏈表的數(shù)據(jù)結(jié)構(gòu)。當(dāng)申請內(nèi)存時,空閑鏈表會一次遍歷空閑的內(nèi)存塊,找到足夠大的內(nèi)存,然后申請新的資源并且修改鏈表
常見的空閑鏈表分配器的策略有
在go語言中的內(nèi)存分配器會基于分配的內(nèi)存大小選擇不同的處理邏輯,運行時根據(jù)對象的大下將對象分成微對象、小對象和大對象三種
類別 | 大小 |
---|---|
微對象 | (0,16B) |
小對象 | [16B,32KB] |
大對象 | (32KB,+∞) |
因為大多數(shù)情況下對象的大小都在32KB以下,而申請的內(nèi)存大小影響Go語言運行時分配內(nèi)存的過程和開銷,所以分別處理大對象和小對象有利于提高內(nèi)存分配器的性能。
內(nèi)存分配器不僅會區(qū)別對待大小不同的對象,還會將內(nèi)存分成不同的級別分別管理,TCMalloc和Go運行時分配器都會引入Thread Cache(線程緩存)、Central Cache(中心緩存)和Page Heap(頁堆)三個組件分級管理內(nèi)存
線程緩存屬于每一個的獨立的線程,它能夠滿足線程上絕大多數(shù)的內(nèi)存分配需求,因為不涉及多線程,所以也不需要使用互斥鎖來保護(hù)內(nèi)存,能夠減少鎖競爭帶來的性能損耗。當(dāng)線程緩存不能滿足需求時,運行時會使用中心緩存作為補(bǔ)充解決小對象的內(nèi)存分配,在遇到32KB以上的對象時,內(nèi)存分配器會選擇頁堆直接分配大內(nèi)存。
這種多層級的內(nèi)存分配設(shè)計與計算機(jī)操作系統(tǒng)中的多級緩存有些類似,因為多數(shù)的對象都是小對象,我們可以通過線程緩存和中心緩存提供足夠的內(nèi)存空間,發(fā)現(xiàn)資源不足時從上一級組件中獲取更多的內(nèi)存資源。
在Go1.11版本之后,使用了稀疏的堆內(nèi)存空間替代了連續(xù)的內(nèi)存,解決了連續(xù)內(nèi)存帶來的限制以及在特殊場景下可能出現(xiàn)的問題。
因為所有的內(nèi)存最終都是要從操作系統(tǒng)中申請的,所以 Go 語言的運行時構(gòu)建了操作系統(tǒng)的內(nèi)存管理抽象層,該抽象層將運行時管理的地址空間分成以下四種狀態(tài)
狀態(tài) | 解釋 |
---|---|
None | 內(nèi)存沒有被保存或者映射,是地址空間的默認(rèn)狀態(tài) |
Reserved | 運行時持有該地址空間,但是訪問該內(nèi)存會導(dǎo)致錯誤 |
Prepared | 內(nèi)存被保留,一般沒有對應(yīng)的物理內(nèi)存訪問該片內(nèi)存的行為是未定義的可以快速轉(zhuǎn)到Ready狀態(tài) |
Ready | 可以被安全訪問 |
到此,相信大家對“go內(nèi)存是怎么分配的”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。