最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang 內(nèi)存對(duì)齊的實(shí)現(xiàn)

 更新時(shí)間:2024年08月14日 11:00:04   作者:m舊褲子  
在代碼編譯階段,編譯器會(huì)對(duì)數(shù)據(jù)的存儲(chǔ)布局進(jìn)行對(duì)齊優(yōu)化,本文主要介紹了golang 內(nèi)存對(duì)齊的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下

什么是內(nèi)存對(duì)齊

在訪問特定類型變量的時(shí)候通常在特定的內(nèi)存地址訪問,這就需要對(duì)這些數(shù)據(jù)在內(nèi)存中存放的位置有限制,各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個(gè)接一個(gè)的排放,這就是對(duì)齊。

內(nèi)存對(duì)齊是編譯器的管轄范圍。表現(xiàn)為:編譯器為程序中的每個(gè)“數(shù)據(jù)單元”安排在適當(dāng)?shù)奈恢蒙稀?/p>

為什么需要內(nèi)存對(duì)齊

  • 有些CPU可以訪問任意地址上的任意數(shù)據(jù),而有些CPU只能在特定地址訪問數(shù)據(jù),因此不同硬件平臺(tái)具有差異性,這樣的代碼就不具有移植性,如果在編譯時(shí),將分配的內(nèi)存進(jìn)行對(duì)齊,這就具有平臺(tái)可以移植性了。

  • CPU 訪問內(nèi)存時(shí)并不是逐個(gè)字節(jié)訪問,而是以字長(word size)為單位訪問,例如 32位的CPU 字長是4字節(jié),64位的是8字節(jié)。如果變量的地址沒有對(duì)齊,可能需要多次訪問才能完整讀取到變量內(nèi)容,而對(duì)齊后可能就只需要一次內(nèi)存訪問,因此內(nèi)存對(duì)齊可以減少CPU訪問內(nèi)存的次數(shù),加大CPU訪問內(nèi)存的吞吐量。

假設(shè)每次訪問的步長為4個(gè)字節(jié),如果未經(jīng)過內(nèi)存對(duì)齊,獲取b的數(shù)據(jù)需要進(jìn)行兩次內(nèi)存訪問,最后再進(jìn)行數(shù)據(jù)整理得到b的完整數(shù)據(jù):

在這里插入圖片描述

如果經(jīng)過內(nèi)存對(duì)齊,一次內(nèi)存訪問就能得到b的完整數(shù)據(jù),減少了一次內(nèi)存訪問:

在這里插入圖片描述

golang中unsafe.AlignOf()函數(shù)

unsafe.AlignOf(x) 方法的返回值是 m,當(dāng)變量進(jìn)行內(nèi)存對(duì)齊時(shí),需要保證分配到 x 的內(nèi)存地址能夠整除 m。因此可以通過這個(gè)方法,確定變量x 在內(nèi)存對(duì)齊時(shí)的地址:

  • 對(duì)于任意類型的變量 x ,unsafe.Alignof(x) 至少為 1。
  • 對(duì)于 struct 結(jié)構(gòu)體類型的變量 x,計(jì)算 x 每一個(gè)字段 f 的 unsafe.Alignof(x.f),unsafe.Alignof(x) 等于其中的最大值。
  • 對(duì)于 array 數(shù)組類型的變量x,unsafe.Alignof(x) 等于構(gòu)成數(shù)組的元素類型的對(duì)齊倍數(shù)。

對(duì)于系統(tǒng)內(nèi)置基礎(chǔ)類型變量 x ,unsafe.Alignof(x) 的返回值就是 min(字長/8,unsafe.Sizeof(x)),即計(jì)算機(jī)字長與類型占用內(nèi)存的較小值:

func main() {
  fmt.Println(unsafe.Alignof(int(1))) // 1 -- min(8,1)
  fmt.Println(unsafe.Alignof(int32(1))) // 4 -- min (8,4)
  fmt.Println(unsafe.Alignof(int64(1))) // 8 -- min (8,8)
  fmt.Println(unsafe.Alignof(complex128(1))) // 8 -- min(8,16)
}  

內(nèi)存對(duì)齊規(guī)則

  • 成員對(duì)齊規(guī)則

針對(duì)一個(gè)基礎(chǔ)類型變量,如果 unsafe.AlignOf() 返回的值是 m,那么該變量的地址需要 被m整除 (如果當(dāng)前地址不能整除,填充空白字節(jié),直至可以整除)。

  • 整體對(duì)齊規(guī)則

針對(duì)一個(gè)結(jié)構(gòu)體,如果 unsafe.AlignOf() 返回值是 m,需要保證該結(jié)構(gòu)體整體內(nèi)存占用是 m的整數(shù)倍,如果當(dāng)前不是整數(shù)倍,需要在后面填充空白字節(jié)。

通過內(nèi)存對(duì)齊后,就可以在保證在訪問一個(gè)變量地址時(shí):

  • 如果該變量占用內(nèi)存小于字長:保證一次訪問就能得到數(shù)據(jù);
  • 如果該變量占用內(nèi)存大于字長:保證第一次內(nèi)存訪問的首地址,是該變量的首地址。

eg:

type A struct {
	a int32
	b int64
	c int32
}

func main() {
	fmt.Println(unsafe.Sizeof(A{1, 1, 1}))  // 24
}

第一個(gè)字段是 int32 類型,unsafe.Sizeof(int32(1))=4,內(nèi)存占用為4個(gè)字節(jié),同時(shí)unsafe.Alignof(int32(1)) = 4,內(nèi)存對(duì)齊需保證變量首地址可以被4整除,我們假設(shè)地址從0開始,0可以被4整除:

在這里插入圖片描述

2. 第二個(gè)字段是 int64 類型,unsafe.Sizeof(int64(1)) = 8,內(nèi)存占用為 8 個(gè)字節(jié),同unsafe.Alignof(int64(1)) = 8,需保證變量放置首地址可以被8整除,當(dāng)前地址為4,距離4最近的且可以被8整除的地址為8,因此需要添加四個(gè)空白字節(jié),從8開始放置:

S

第三個(gè)字段是 int32 類型,unsafe.Sizeof(int32(1))=4,內(nèi)存占用為4個(gè)字節(jié),同時(shí)unsafe.Alignof(int32(1)) = 4,內(nèi)存對(duì)齊需保證變量首地址可以被4整除,當(dāng)前地址為16,16可以被4整除:

在這里插入圖片描述

所有成員對(duì)齊都已經(jīng)完成,現(xiàn)在我們需要看一下整體對(duì)齊規(guī)則:unsafe.Alignof(A{}) = 8,即三個(gè)變量成員的最大值,內(nèi)存對(duì)齊需要保證該結(jié)構(gòu)體的內(nèi)存占用是 8 的整數(shù)倍,當(dāng)前內(nèi)存占用是 20個(gè)字節(jié),因此需要再補(bǔ)充4個(gè)字節(jié):

在這里插入圖片描述

最終該結(jié)構(gòu)體的內(nèi)存占用為 24字節(jié)。

type B struct {
	a int32
	b int32
	c int64
}

func main() {
	fmt.Println(unsafe.Sizeof(B{1, 1, 1}))  // 16
}

第一個(gè)字段是 int32 類型,unsafe.Sizeof(int32(1))=4,內(nèi)存占用為4個(gè)字節(jié),同時(shí)unsafe.Alignof(int32(1)) = 4,內(nèi)存對(duì)齊需保證變量首地址可以被4整除,我們假設(shè)地址從0開始,0可以被4整除:

在這里插入圖片描述

第二個(gè)字段是 int32 類型,unsafe.Sizeof(int32(1))=4,內(nèi)存占用為4個(gè)字節(jié),同時(shí)unsafe.Alignof(int32(1)) = 4,內(nèi)存對(duì)齊需保證變量首地址可以被4整除,當(dāng)前地址為4,4可以被4整除:

在這里插入圖片描述

第三個(gè)字段是 int64 類型,unsafe.Sizeof(int64(1))=8,內(nèi)存占用為8個(gè)字節(jié),同時(shí)unsafe.Alignof(int64(1)) = 8,內(nèi)存對(duì)齊需保證變量首地址可以被8整除,當(dāng)前地址為8,8可以被8整除:

在這里插入圖片描述

所有成員對(duì)齊都已經(jīng)完成,現(xiàn)在我們需要看一下整體對(duì)齊規(guī)則:unsafe.Alignof(B{}) = 8,即三個(gè)變量成員的最大值,內(nèi)存對(duì)齊需要保證該結(jié)構(gòu)體的內(nèi)存占用是 8 的整數(shù)倍,當(dāng)前內(nèi)存占用是 16個(gè)字節(jié),已經(jīng)符合規(guī)則,最終該結(jié)構(gòu)體的內(nèi)存占用為 16個(gè)字節(jié)。

空結(jié)構(gòu)體對(duì)齊規(guī)則

如果空結(jié)構(gòu)體作為結(jié)構(gòu)體的內(nèi)置字段:當(dāng)變量位于結(jié)構(gòu)體的前面和中間時(shí),不會(huì)占用內(nèi)存;當(dāng)該變量位于結(jié)構(gòu)體的末尾位置時(shí),需要進(jìn)行內(nèi)存對(duì)齊,內(nèi)存占用大小和前一個(gè)變量的大小保持一致。

type C struct {
	a struct{}
	b int64
	c int64
}

type D struct {
	a int64
	b struct{}
	c int64
}

type E struct {
	a int64
	b int64
	c struct{}
}

type F struct {
	a int32
	b int32
	c struct{}
}

func main() {
	fmt.Println(unsafe.Sizeof(C{})) // 16
	fmt.Println(unsafe.Sizeof(D{})) // 16
	fmt.Println(unsafe.Sizeof(E{})) // 24
    fmt.Println(unsafe.Sizeof(F{})) // 12
}

參考:https://juejin.cn/post/7077833959047954463

到此這篇關(guān)于golang 內(nèi)存對(duì)齊的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)golang 內(nèi)存對(duì)齊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Go語言實(shí)現(xiàn)應(yīng)用IP防火墻

    基于Go語言實(shí)現(xiàn)應(yīng)用IP防火墻

    在公司里面經(jīng)常會(huì)聽到某應(yīng)用有安全漏洞問題,沒有做安全加固,IP防火墻就是一個(gè)典型的安全加固解決方案,下面我們就來學(xué)習(xí)一下如何使用go語言實(shí)現(xiàn)IP防火墻吧
    2023-11-11
  • Go實(shí)現(xiàn)JWT認(rèn)證中間件的項(xiàng)目實(shí)戰(zhàn)

    Go實(shí)現(xiàn)JWT認(rèn)證中間件的項(xiàng)目實(shí)戰(zhàn)

    本文將介紹在Gin框架中實(shí)現(xiàn)完整的JWT認(rèn)證方案,同時(shí)包含靈活的?Redis?集成選項(xiàng),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • Go語言中的time.Tick 函數(shù)用法解讀

    Go語言中的time.Tick 函數(shù)用法解讀

    Go1.23+中time.Tick自動(dòng)回收資源,適配長期定時(shí)任務(wù);NewTicker需手動(dòng)Stop(),適合需精細(xì)控制的場景,簡單任務(wù)推薦Tick,復(fù)雜需求或舊版本仍建議NewTicker+defer Stop()
    2025-07-07
  • Go1.18新特性之泛型使用三步曲(小結(jié))

    Go1.18新特性之泛型使用三步曲(小結(jié))

    本文主要介紹了Go1.18新特性之泛型,是Go1.18的新特性,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Go1.21新增slices包的用法詳解

    Go1.21新增slices包的用法詳解

    Go?1.21新增的?slices?包提供了很多和切片相關(guān)的函數(shù),可以用于任何類型的切片,這篇文章主要來和大家介紹一下slices包中相關(guān)函數(shù)的用法,需要的可以參考一下
    2023-08-08
  • go語言實(shí)現(xiàn)一個(gè)簡單的http客戶端抓取遠(yuǎn)程url的方法

    go語言實(shí)現(xiàn)一個(gè)簡單的http客戶端抓取遠(yuǎn)程url的方法

    這篇文章主要介紹了go語言實(shí)現(xiàn)一個(gè)簡單的http客戶端抓取遠(yuǎn)程url的方法,實(shí)例分析了Go語言http操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • 淺談Go-zero構(gòu)建RPC與API服務(wù)全流程

    淺談Go-zero構(gòu)建RPC與API服務(wù)全流程

    Go Zero 是一個(gè)流行的框架,它提供了構(gòu)建微服務(wù)的基礎(chǔ)設(shè)施,包括 RPC 服務(wù)和 RESTful API,本文主要介紹了Go-zero構(gòu)建RPC與API服務(wù)全流程,感興趣的可以了解一下
    2025-09-09
  • Go基本數(shù)據(jù)類型的具體使用

    Go基本數(shù)據(jù)類型的具體使用

    本文主要介紹了Go的基本數(shù)據(jù)類型,包括布爾類型、整數(shù)類型、浮點(diǎn)數(shù)類型、復(fù)數(shù)類型、字符串類型,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Golang定時(shí)器Timer與Ticker的使用詳解

    Golang定時(shí)器Timer與Ticker的使用詳解

    在 Go 里有很多種定時(shí)器的使用方法,像常規(guī)的 Timer、Ticker 對(duì)象,本文主要為大家介紹了Timer與Ticker的使用,感興趣的小伙伴可以了解一下
    2023-05-05
  • 詳解Golang如何優(yōu)雅的終止一個(gè)服務(wù)

    詳解Golang如何優(yōu)雅的終止一個(gè)服務(wù)

    后端服務(wù)通常會(huì)需要?jiǎng)?chuàng)建子協(xié)程來進(jìn)行相應(yīng)的作業(yè),但進(jìn)程接受到終止信號(hào)或正常結(jié)束時(shí),并沒有判斷或等待子協(xié)程執(zhí)行結(jié)束,下面這篇文章主要給大家介紹了關(guān)于Golang如何優(yōu)雅的終止一個(gè)服務(wù)的相關(guān)資料,需要的朋友可以參考下
    2022-03-03

最新評(píng)論

淳化县| 泗水县| 龙泉市| 贡嘎县| 抚顺县| 清水县| 中方县| 手机| 天等县| 漳州市| 涪陵区| 九江市| 南皮县| 临泉县| 东源县| 北海市| 绥宁县| 凤庆县| 灵武市| 冕宁县| 桃源县| 峡江县| 泸定县| 白山市| 兴城市| 温宿县| 故城县| 灵台县| 兰溪市| 高阳县| 潢川县| 墨脱县| 湖北省| 噶尔县| 普宁市| 嘉义市| 弥勒县| 临海市| 乌什县| 陵水| 东山县|