文中所涉及到的代碼運(yùn)行結(jié)果均是在64位機(jī)器上執(zhí)行得到的.
基礎(chǔ)知識(shí)回顧
在Go中,我們可以使用unsafe.Sizeof(x)
來查看變量所占的內(nèi)存大小。以下是Go內(nèi)置的數(shù)據(jù)類型占用的內(nèi)存大?。?/p>
類型 | 內(nèi)存大小(字節(jié)數(shù)) |
---|---|
bool | 1 |
int8/uint8 | 1 |
int/uint | 8 |
int32/uint32 | 4 |
int64/uint64 | 8 |
float32 | 4 |
float64 | 8 |
complex64 | 8 |
complex128 | 16 |
指針類型:*T, map,func,chan | 8 |
string | 16 |
interface | 16 |
[]T | 24 |
func main() {
fmt.Println(unsafe.Sizeof(true)) // 1
fmt.Println(unsafe.Sizeof(int8(1))) // 1
fmt.Println(unsafe.Sizeof(int(1))) // 8
fmt.Println(unsafe.Sizeof(int32(1))) // 4
fmt.Println(unsafe.Sizeof(int64(1))) // 8
fmt.Println(unsafe.Sizeof(float32(1.0))) // 4
fmt.Println(unsafe.Sizeof(float64(1.0))) // 8
a := int(1)
fmt.Println(unsafe.Sizeof(&a)) // 8
s := "1234"
fmt.Println(unsafe.Sizeof(s)) //16
var b interface{}
fmt.Println(unsafe.Sizeof(b)) //16
fmt.Println(unsafe.Sizeof([]string{})) // 24
fmt.Println(unsafe.Sizeof([]int{})) // 24
}
簡單示例
對(duì)于一個(gè)結(jié)構(gòu)體,其占用的內(nèi)存大小應(yīng)該是其內(nèi)部多個(gè)基礎(chǔ)類型占用內(nèi)存大小之和。但實(shí)際情況并非如此,甚至字段順序不同,結(jié)構(gòu)體的大小也不同:
type Example1 struct {
a int32 // 4
b int32 // 4
c int64 // 8
}
type Example2 struct {
a int32 // 4
c int64 // 8
b int32 // 4
}
type Example3 struct {
a bool // 1
b int8 // 1
c string // 16
}
func main() {
fmt.Println(unsafe.Sizeof(Example1{})) // 16
fmt.Println(unsafe.Sizeof(Example2{})) // 24
fmt.Println(unsafe.Sizeof(Example3{})) // 24,并不是1+1+16=18
}
為什么會(huì)出現(xiàn)上面的情況呢?這就引出了本文的重點(diǎn):內(nèi)存對(duì)齊。
內(nèi)存對(duì)齊
內(nèi)存對(duì)齊(Memory Alignment)是指數(shù)據(jù)在計(jì)算機(jī)內(nèi)存中存儲(chǔ)時(shí)按照特定規(guī)則對(duì)齊到內(nèi)存地址的過程。內(nèi)存對(duì)齊是由計(jì)算機(jī)硬件和操作系統(tǒng)所決定的,它可以提高內(nèi)存訪問效率和系統(tǒng)性能。
在計(jì)算機(jī)體系結(jié)構(gòu)中,內(nèi)存是以字節(jié)(byte)為單位進(jìn)行訪問的。數(shù)據(jù)類型在內(nèi)存中占用的字節(jié)數(shù)可以是不同的,例如,整數(shù)可能占用2字節(jié)、4字節(jié)或8字節(jié),而字符可能只占用1字節(jié)。
內(nèi)存對(duì)齊的規(guī)則要求變量的地址必須是其數(shù)據(jù)類型字節(jié)數(shù)的整數(shù)倍。例如,如果一個(gè)變量的數(shù)據(jù)類型是4字節(jié)(32位),那么它的起始地址必須是4的倍數(shù)。
內(nèi)存對(duì)齊的主要目的是優(yōu)化計(jì)算機(jī)的內(nèi)存訪問性能。當(dāng)數(shù)據(jù)按照對(duì)齊要求存儲(chǔ)在內(nèi)存中時(shí),讀取和寫入操作可以更高效地進(jìn)行。如果數(shù)據(jù)沒有按照對(duì)齊要求存儲(chǔ),計(jì)算機(jī)可能需要進(jìn)行多次內(nèi)存讀取操作來獲取完整的數(shù)據(jù),這會(huì)增加訪問延遲和降低系統(tǒng)性能。
在編程中,特別是在使用結(jié)構(gòu)體和類的語言中,內(nèi)存對(duì)齊是一個(gè)重要的概念。編譯器會(huì)根據(jù)數(shù)據(jù)類型的對(duì)齊要求自動(dòng)進(jìn)行內(nèi)存對(duì)齊操作,以確保數(shù)據(jù)存儲(chǔ)的正確性和性能優(yōu)化。但在某些情況下,可以通過顯式地設(shè)置對(duì)齊屬性來控制數(shù)據(jù)的對(duì)齊方式,以滿足特定的需求。
需要注意的是,不同的硬件平臺(tái)和操作系統(tǒng)可能具有不同的內(nèi)存對(duì)齊規(guī)則和要求。因此,在開發(fā)跨平臺(tái)應(yīng)用程序時(shí),應(yīng)當(dāng)考慮到這些差異并遵循適當(dāng)?shù)膬?nèi)存對(duì)齊規(guī)則。
為什么需要對(duì)齊內(nèi)存
內(nèi)存對(duì)齊是為了提高計(jì)算機(jī)系統(tǒng)的內(nèi)存訪問效率和性能而存在的。以下是幾個(gè)需要內(nèi)存對(duì)齊的原因:
- 硬件要求:許多計(jì)算機(jī)硬件和體系結(jié)構(gòu)對(duì)內(nèi)存訪問有特定的對(duì)齊要求。如果數(shù)據(jù)沒有按照硬件要求進(jìn)行對(duì)齊,可能會(huì)導(dǎo)致訪問錯(cuò)誤、異常或性能下降。通過滿足硬件對(duì)齊要求,可以確保數(shù)據(jù)能夠按照有效的方式訪問,提高系統(tǒng)的穩(wěn)定性和性能。
- 內(nèi)存訪問效率:當(dāng)數(shù)據(jù)按照對(duì)齊要求存儲(chǔ)在內(nèi)存中時(shí),計(jì)算機(jī)系統(tǒng)可以更高效地訪問這些數(shù)據(jù)。對(duì)齊數(shù)據(jù)可以減少或避免多次內(nèi)存訪問,提高數(shù)據(jù)的讀取和寫入速度。這對(duì)于大量的數(shù)據(jù)操作和高性能計(jì)算非常重要。
- 緩存性能:現(xiàn)代計(jì)算機(jī)系統(tǒng)中通常有多級(jí)緩存,而緩存的訪問是以特定塊的方式進(jìn)行的。內(nèi)存對(duì)齊可以確保數(shù)據(jù)按照緩存塊的大小對(duì)齊,使得數(shù)據(jù)能夠更好地利用緩存,減少緩存未命中和讀取延遲,提高緩存性能。
- 結(jié)構(gòu)體和類的內(nèi)存布局:結(jié)構(gòu)體和類通常包含多個(gè)成員變量,這些變量按照一定的順序存儲(chǔ)在內(nèi)存中。內(nèi)存對(duì)齊確保結(jié)構(gòu)體和類的成員變量按照正確的順序和對(duì)齊要求進(jìn)行存儲(chǔ),避免內(nèi)存空洞和訪問錯(cuò)誤,保證數(shù)據(jù)的正確性和一致性。
總之,內(nèi)存對(duì)齊是為了滿足硬件要求、提高內(nèi)存訪問效率和性能而引入的機(jī)制。通過合理地進(jìn)行內(nèi)存對(duì)齊,可以提高系統(tǒng)的穩(wěn)定性、性能和響應(yīng)速度,并避免潛在的內(nèi)存訪問問題。
如何對(duì)齊內(nèi)存
Go團(tuán)隊(duì)開發(fā)了一款名為fieldalignment
的工具可以幫助我們解決內(nèi)存對(duì)齊的問題。
使用下面的命令安裝fieldalignment
工具:
$ go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest
還是以上面的代碼為例,可以執(zhí)行下面的命令:
$ fieldalignment main.go
main.go:14:15: struct of size 24 could be 16
main.go:20:15: struct with 16 pointer bytes could be 8
也可以使用--fix
參數(shù)直接修改代碼:
$ fieldalignment --fix main.go
修改后的內(nèi)容如下:文章來源:http://www.zghlxwxcb.cn/news/detail-473202.html
type Example1 struct {
a int32 // 4
b int32 // 4
c int64 // 8
}
type Example2 struct {
c int64
a int32
b int32
}
type Example3 struct {
c string
a bool
b int8
}

聲明:本作品采用署名-非商業(yè)性使用-相同方式共享 4.0 國際 (CC BY-NC-SA 4.0)進(jìn)行許可,使用時(shí)請(qǐng)注明出處。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 戀水無意文章來源地址http://www.zghlxwxcb.cn/news/detail-473202.html
到了這里,關(guān)于如何讓你的結(jié)構(gòu)體更高效的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!