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

golang內(nèi)存對(duì)齊的概念及案例詳解

 更新時(shí)間:2022年02月02日 09:10:52   作者:Dawnlight-_-  
為保證程序順利高效的運(yùn)行,編譯器會(huì)把各種類型的數(shù)據(jù)安排到合適的地址,并占用合適的長(zhǎng)度,這就是內(nèi)存對(duì)齊。本文重點(diǎn)給大家介紹golang內(nèi)存對(duì)齊的概念及案例詳解,感興趣的朋友一起看看吧

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

為保證程序順利高效的運(yùn)行,編譯器會(huì)把各種類型的數(shù)據(jù)安排到合適的地址,并占用合適的長(zhǎng)度,這就是內(nèi)存對(duì)齊。

每種類型的對(duì)齊值就是它的對(duì)齊邊界,內(nèi)存對(duì)齊要求數(shù)據(jù)存儲(chǔ)地址以及占用的字節(jié)數(shù)都要是它的對(duì)齊邊界的倍數(shù)。所以下述的int32要錯(cuò)開(kāi)兩個(gè)字節(jié),從4開(kāi)始存,卻不能緊接著從2開(kāi)始。

也可以這樣解釋:

CPU把內(nèi)存當(dāng)成是一塊一塊的,塊的大小可以是2,4,8,16字節(jié)大小,因此CPU在讀取內(nèi)存時(shí)是一塊一塊進(jìn)行讀取的。塊大小成為memory access granularity(粒度)。

如果不進(jìn)行內(nèi)存對(duì)齊

比如我們想從地址1開(kāi)始讀8字節(jié)的數(shù)據(jù):

CPU會(huì)分兩次讀:

  • 第一次從 0 - 7 但只取后 7 字節(jié)。
  • 第二次從 8 - 15 但只取第 1 字節(jié)。

分兩次讀,這樣勢(shì)必會(huì)對(duì)性能造成影響。

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

原因主要有兩點(diǎn):

  • 平臺(tái)原因(移植原因):不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。
  • 性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對(duì)齊。原因在于,為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪問(wèn)。

對(duì)齊邊界

那該怎么確定每種數(shù)據(jù)的對(duì)齊邊界呢?這和平臺(tái)有關(guān),go語(yǔ)言支持這些平臺(tái):

可以看到常見(jiàn)的32位平臺(tái),指針寬度和寄存器寬度都是4字節(jié),64位平臺(tái)上都是8字節(jié)。而被go語(yǔ)言稱為寄存器寬度的這個(gè)值,就可以理解為機(jī)器字長(zhǎng),也是平臺(tái)對(duì)應(yīng)的最大對(duì)齊邊界。

而數(shù)據(jù)類型的對(duì)齊邊界,是取類型大小與平臺(tái)最大對(duì)齊邊界中較小的那個(gè)。不過(guò)要注意,同一個(gè)類型在不同平臺(tái)上,大小可能不同,對(duì)齊邊界也可能不同。

為什么不統(tǒng)一使用平臺(tái)最大對(duì)齊邊界呢?或者統(tǒng)一按各類型大小來(lái)對(duì)齊呢?

我們來(lái)試一下,假設(shè)目前是64位平臺(tái),最大對(duì)齊邊界為8字節(jié)。int8只有1字節(jié),按照1字節(jié)對(duì)齊的話,它可以放在任何位置,因?yàn)榭偰芡ㄟ^(guò)一次讀取把它完整拿出來(lái)。如果統(tǒng)一對(duì)齊到8字節(jié),雖然同樣只要讀取一次,但每個(gè)int8的變量都要浪費(fèi)7字節(jié),所以對(duì)齊到1。

int16占2字節(jié),按照2字節(jié)對(duì)齊,可以從這些地址開(kāi)始存,而且能保證只用讀取一次。

如果按1字節(jié)對(duì)齊就可能存成這樣,那就要讀取兩次再截取拼接,會(huì)影響性能。

如果按8字節(jié)對(duì)齊,會(huì)與int8一樣浪費(fèi)內(nèi)存,所以對(duì)齊到2。

這是小于最大對(duì)齊邊界的情況,再來(lái)看看大于的情況。

假設(shè)要在32位的平臺(tái)下存儲(chǔ)一個(gè)int64類型的數(shù)據(jù),在0和1位置被占用的情況下,就要從位置8開(kāi)始存。而如果對(duì)齊到4,就可以從位置4開(kāi)始,內(nèi)存浪費(fèi)更少,所以選擇對(duì)齊到4。

因此類型對(duì)齊邊界會(huì)這樣選擇,依然是為了減少浪費(fèi)提升性能。

GO 計(jì)算對(duì)齊邊界函數(shù)

在go語(yǔ)言中可以調(diào)用 unsafe.Alignof 來(lái)返回相應(yīng)類型的對(duì)齊邊界:

func main() {
	fmt.Printf("bool align: %d\n", unsafe.Alignof(bool(true)))
	fmt.Printf("int32 align: %d\n", unsafe.Alignof(int32(0)))
	fmt.Printf("int8 align: %d\n", unsafe.Alignof(int8(0)))
	fmt.Printf("int64 align: %d\n", unsafe.Alignof(int64(0)))
	fmt.Printf("byte align: %d\n", unsafe.Alignof(byte(0)))
	fmt.Printf("string align: %d\n", unsafe.Alignof("EDDYCJY"))
	fmt.Printf("map align: %d\n", unsafe.Alignof(map[string]string{}))
}

運(yùn)行結(jié)果:

bool align: 1
int32 align: 4
int8 align: 1
int64 align: 8
byte align: 1
string align: 8
map align: 8

確定結(jié)構(gòu)體的對(duì)齊邊界

對(duì)結(jié)構(gòu)體而言,首先要確定每個(gè)成員的對(duì)齊邊界,然后取其中最大的,這就是這個(gè)結(jié)構(gòu)體的對(duì)齊邊界。

然后來(lái)存儲(chǔ)這個(gè)結(jié)構(gòu)體變量:

內(nèi)存對(duì)齊要求一:

  • 存儲(chǔ)這個(gè)結(jié)構(gòu)體的起始地址,是對(duì)齊邊界的倍數(shù)。

?假設(shè)從0開(kāi)始存,結(jié)構(gòu)體的每個(gè)成員在存儲(chǔ)時(shí),都要把這個(gè)起始地址當(dāng)作地址0,然后再用相對(duì)地址來(lái)決定自己該放在哪里。

內(nèi)存對(duì)齊要求2:

  • 結(jié)構(gòu)體整體占用字節(jié)數(shù)需要是類型對(duì)齊邊界的倍數(shù),不夠的話要往后擴(kuò)張一下。

?所以最終上述結(jié)構(gòu)體類型的大小就是24字節(jié)。

案例

type Part1 struct {
	a bool
	b int32
	c int8
	d int64
	e byte
}
type Part2 struct {
	a bool
	c int8
	e byte
	b int32 // 4個(gè)字節(jié)
	d int64
}

分別求以上兩個(gè)結(jié)構(gòu)體占用的字節(jié):

fmt.Printf("part1 size: %d, align: %d\n", unsafe.Sizeof(part1), unsafe.Alignof(part1))
fmt.Printf("part2 size: %d, align: %d\n", unsafe.Sizeof(part2), unsafe.Alignof(part2))

這里我們直接調(diào)用函數(shù)求得:

part1 size: 32, align: 8
part2 size: 16, align: 8

原因請(qǐng)讀者來(lái)思考。

參考資料:
https://blog.csdn.net/u010853261/article/details/102557188
https://www.bilibili.com/video/BV1Ja4y1i7AF?from=search&seid=16213689667007976568&spm_id_from=333.337.0.0

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

相關(guān)文章

  • golang結(jié)構(gòu)化日志log/slog包之LogValuer的用法簡(jiǎn)介

    golang結(jié)構(gòu)化日志log/slog包之LogValuer的用法簡(jiǎn)介

    這篇文章主要為大家詳細(xì)介紹了golang結(jié)構(gòu)化日志log/slog包中 LogValuer 和日志記錄函數(shù)的正確包裝方法,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-10-10
  • go語(yǔ)言實(shí)現(xiàn)AES加密的方法

    go語(yǔ)言實(shí)現(xiàn)AES加密的方法

    這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)AES加密的方法,實(shí)例分析了Go語(yǔ)言的加密技巧,需要的朋友可以參考下
    2015-03-03
  • Go語(yǔ)言開(kāi)發(fā)redis封裝及簡(jiǎn)單使用詳解

    Go語(yǔ)言開(kāi)發(fā)redis封裝及簡(jiǎn)單使用詳解

    這篇文章主要為大家介紹了Go語(yǔ)言開(kāi)發(fā)redis的封裝及簡(jiǎn)單使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • golang通過(guò)反射設(shè)置結(jié)構(gòu)體變量的值

    golang通過(guò)反射設(shè)置結(jié)構(gòu)體變量的值

    這篇文章主要介紹了golang通過(guò)反射設(shè)置結(jié)構(gòu)體變量的值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Golang中Map按照Value大小排序的方法實(shí)例

    Golang中Map按照Value大小排序的方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于Golang中Map按照Value大小排序的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • go語(yǔ)言LeetCode題解1030距離順序排列矩陣單元格

    go語(yǔ)言LeetCode題解1030距離順序排列矩陣單元格

    這篇文章主要為大家介紹了go語(yǔ)言LeetCode題解1030距離順序排列矩陣單元格,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang sync包中errgroup的使用詳解

    Golang sync包中errgroup的使用詳解

    Go 語(yǔ)言為我們提供了豐富的并發(fā)原語(yǔ),且大多數(shù)都位于 sync 包下,今天我們來(lái)探討一下該庫(kù)下的原語(yǔ)之一:errgroup,感興趣的小伙伴可以了解一下
    2023-05-05
  • Go語(yǔ)言實(shí)現(xiàn)23種設(shè)計(jì)模式的使用

    Go語(yǔ)言實(shí)現(xiàn)23種設(shè)計(jì)模式的使用

    設(shè)計(jì)模式是軟件工程中各種常見(jiàn)問(wèn)題的經(jīng)典解決方案,,本文主要介紹了Go語(yǔ)言實(shí)現(xiàn)23種設(shè)計(jì)模式的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Go語(yǔ)言單鏈表實(shí)現(xiàn)方法

    Go語(yǔ)言單鏈表實(shí)現(xiàn)方法

    這篇文章主要介紹了Go語(yǔ)言單鏈表實(shí)現(xiàn)方法,實(shí)例分析了基于Go語(yǔ)言的單鏈表實(shí)現(xiàn)原理與使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理分析

    Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理分析

    這篇文章主要介紹了Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理,HTTP服務(wù)的超時(shí)控制是保障服務(wù)高可用性的重要措施之一,由于HTTP服務(wù)可能會(huì)遇到網(wǎng)絡(luò)延遲,資源瓶頸等問(wèn)題,因此需要對(duì)請(qǐng)求進(jìn)行超時(shí)控制,以避免服務(wù)雪崩等問(wèn)題,需要的朋友可以參考下
    2023-05-05

最新評(píng)論

武邑县| 洱源县| 汨罗市| 鹿泉市| 高邮市| 靖安县| 四会市| 宁乡县| 漯河市| 郧西县| 杭州市| 苍南县| 凤城市| 紫云| 福海县| 班戈县| 大方县| 龙海市| 乌拉特前旗| 宁城县| 囊谦县| 孝感市| 沿河| 屯昌县| 肥东县| 米林县| 盐城市| 台南县| 营口市| 汝州市| 视频| 云安县| 特克斯县| 永定县| 北流市| 和静县| 东辽县| 崇仁县| 乐昌市| 固原市| 哈巴河县|