欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

GoLang內(nèi)存模型詳細(xì)講解

 更新時間:2022年12月15日 10:39:48   作者:上后左愛  
go官方介紹go內(nèi)存模型的時候說:探究在什么條件下,goroutine 在讀取一個變量的值的時,能夠看到其它 goroutine 對這個變量進(jìn)行的寫的結(jié)果,Go內(nèi)存模型規(guī)定了一些條件,在這些條件下,在一個goroutine中讀取變量返回的值能夠確保是另一個goroutine中對該變量寫入的值

棧內(nèi)存-協(xié)程棧-調(diào)用棧

為什么go的棧是在堆上?

go 協(xié)程棧的位置: go的協(xié)程棧位于go的堆內(nèi)存,go 的gc 也是對堆上內(nèi)存進(jìn)行GC, go堆內(nèi)存位于操作系統(tǒng)虛擬內(nèi)存上, 記錄局部變量,傳遞參數(shù)和返回值 ,go 使用的參數(shù)拷貝傳遞,如果傳遞的值比較大 注意傳遞其指針

go 參數(shù)傳遞 使用 值傳遞, 也就是說傳遞結(jié)構(gòu)體時候,拷貝結(jié)構(gòu)體的指針,傳遞結(jié)構(gòu)體指針時候 拷貝的結(jié)構(gòu)體指針 所以對于 只讀參數(shù),不進(jìn)行修改,最好傳遞結(jié)構(gòu)體指針

協(xié)程棧的空間不夠大 怎么辦?

本地變量太大,棧幀太多

逃逸分析

不是所有的變量都放在協(xié)程棧上,棧幀回收后,需要繼續(xù)使用的變量,或者 太大的變量,分為指針逃逸,空接口逃逸和大變量逃逸,從棧逃逸分配到堆空間上

指針逃逸 (函數(shù)返回的指針被其他使用)

func a() *int {
	v :=0
	return &v // 導(dǎo)致 局部變量會分配在堆行 不會分配棧上
}

空接口逃逸(函數(shù)的參數(shù)是interface{} 函數(shù)的實參很可能會逃逸,主要因為interface{} 類型函數(shù)往往會使用反射)

fmt.Println(i) // 入?yún)儆趇nterface{} 空接口, 是否有反射查看值是什么類型 逃逸到堆上

大變量逃逸(過大變量導(dǎo)致的空間不足,超過64KB的變量會逃逸)

// 解決協(xié)程的??臻g不足

調(diào)用棧幀太多(棧擴容)

  • 解決方式 進(jìn)行棧擴容,Go的棧初始空間為2KB
  • 在函數(shù)調(diào)用前判斷??臻gmorestack
  • 早期使用分段棧(go 1.13) 在邏輯上連接,優(yōu)點沒有空間浪費,棧指針會在不連續(xù)的空間跳轉(zhuǎn),后期 連續(xù)棧,缺點 伸縮時候開銷大,擴容為原來2倍, 使用比例不足1/4, 變?yōu)樵瓉淼?1/2

go 堆內(nèi)存

操作系統(tǒng)的虛擬內(nèi)存:操作系統(tǒng)給應(yīng)用提供的虛擬的內(nèi)存的空間,背后也是物理內(nèi)存或者磁盤

go 使用 heapArena每次申請?zhí)摂M內(nèi)存單元 64MB,所有的heapArena 組成 堆內(nèi)存

線性分配據(jù)或者鏈表分配出現(xiàn)空間碎片,所有g(shù)o 語言中使用分級分配,避免內(nèi)存的碎片化,每個內(nèi)存進(jìn)行分級思想, mspan n內(nèi)存管理單元

按照需求進(jìn)行分級分配,runtime.sizeclass.go 進(jìn)行分配, 總共有68 個級別。

其中 136 個span , mcentral 屬于鏈接頭,其中 68個需要GC掃描,其他68個不需要GC掃描。 mcentral 的屬于中心索引,使用互斥鎖保護(hù),在高并發(fā)的場景下 鎖沖突嚴(yán)重,參考GMP模型,增加線程的本地緩存。

  • Go 模仿TCmalloc ,建立自己的堆內(nèi)存架構(gòu)
  • 使用heapArena 向操作系統(tǒng)申請內(nèi)存,以mspan 為單位,防止碎片化
  • mcentral 是mspan 的中心索引
  • 使用mcache 本地緩存 大大降低 鎖競爭問題

堆如何進(jìn)行分配

  • Tiny 微對象(0,16B)無指針 – 分配到普通mspan(class 1 - class 67) --將多個微級對象合并成16Byte
  • Small 對象[16B, 32K] – 定制作mspan (class 0)
  • Large 大對象(32KB, +)
  • heapArena 不足的化 會自動申請擴容

go 語言對象的垃圾回收

  • 標(biāo)記-清除
  • 標(biāo)記-整理 (go 語言使用分級分配 不需要標(biāo)記整理)
  • 標(biāo)記-復(fù)制 (只有用內(nèi)存進(jìn)行復(fù)制,但是空間浪費非常大,Java的新生代) 總結(jié): Go 堆內(nèi)存的獨特方式 進(jìn)行標(biāo)記清除掉,如何尋找有用?
  • Gc的起點: 1. 被棧上的指針引用 2.被全局變量引用 3.被寄存器中指針引用
  • Root 節(jié)點進(jìn)行廣度優(yōu)先策略進(jìn)行搜索(可達(dá)性分析標(biāo)記方法)
  • 暫停所有其他協(xié)程,進(jìn)行可達(dá)性分析,找到無引用的GC 屬于串行GC 屬于在OLD version 中

如何減少GC對性能的分析

如何進(jìn)行并行GC 提升性能?

難點在于如何進(jìn)行標(biāo)記階段,go 語言采用的 三色標(biāo)記方法

  • 黑色: 表示已經(jīng)分析掃描,有用
  • 灰色: 有用,還沒進(jìn)行分析掃描 DFS代替隊列
  • 白色: 暫時無用

當(dāng)三色標(biāo)記結(jié)束后只有黑色的對象,下一次開啟恢復(fù)成 白色

并發(fā)標(biāo)記的問題(刪除)-- 在GC時候 進(jìn)行對象的指針的變動,針對 并發(fā)標(biāo)記問題 使用 Yuasa 刪除屏障, 強制將釋放的C指針變成灰色,避免 在GC過程中被粗我?標(biāo)記

Yuasa 刪除屏障(s釋放的指針進(jìn)行強制為灰色)

1. 刪除屏障可以杜絕在GC標(biāo)記中刪除的問題 ,但是也無法解決并發(fā)標(biāo)記的插入問題

針對插入屏障 使用 Dijkstra 插入屏障 并發(fā)標(biāo)記過程中 將C進(jìn)行強制置灰,當(dāng)并發(fā)標(biāo)記過程,新指針指向新的對象,新增的依賴對象 防止錯誤的GC

混合屏障

被刪除的堆對象標(biāo)記成為灰色

被添加的堆對象標(biāo)記成為灰色

并發(fā)垃圾回收關(guān)鍵在于標(biāo)記安全,兼顧的安全的效率

GC 優(yōu)化效率

GC觸發(fā)的時機

系統(tǒng)定時觸發(fā)

g0 協(xié)程內(nèi)的sysmon 定時檢查 ,在2min 內(nèi) forcegcperiod 沒有過GC,觸發(fā),謹(jǐn)慎調(diào)整

用戶顯示觸發(fā)

調(diào)用runtime.gc 并不推薦

申請內(nèi)存觸發(fā)

給申請對象的時候伴隨著GC

GC優(yōu)化原則

盡量少在堆上產(chǎn)生垃圾

內(nèi)存池化(channel 中 環(huán)形池)

減少逃逸 (fmt 包, 返回了指針不是拷貝)

使用空結(jié)構(gòu)體 (不占用空結(jié)構(gòu)體,使用channel 傳遞空結(jié)構(gòu)體)

使用如下的方式 查看內(nèi)存

$env:GODEBUG="gctrace=1"

到此這篇關(guān)于GoLang內(nèi)存模型詳細(xì)講解的文章就介紹到這了,更多相關(guān)Go內(nèi)存模型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論