序
Golang 中的結構或 struct 是用戶定義的型別,允許將可能不同型別的項分組/組合為單一型別,
可以說是一個不支持繼承但支持組合的輕量級類,
我們使用 Golang 撰寫代碼的時候,你肯定使用過struct,
但是,你可能不知道的是,通過簡單地重新排序結構中的欄位,可以極大地提高 Go 程式的速度和記憶體使用率!
示例演示
type EmployeeStruct struct {
IsPublic bool
Age int64
Status bool
Name string
Image float32
}
我們來看一下Employee結構體的記憶體大小:
- IsPublic(boolean) 1 位元組
- Age(int64) 8 位元組
- Status(boolean) 1 位元組
- Name(string) 16 位元組
- Image(float32) 4 位元組
總計: 30 位元組
通過unsafe.Sizeof檢查一下:
package main
import (
"fmt"
"unsafe"
)
type EmployeeStruct struct {
IsPublic bool
Age int64
Status bool
Name string
Image float32
}
func main() {
var employee EmployeeStruct
fmt.Println(unsafe.Sizeof(employee))
}
執行后輸出: 48位元組,為什么呢?
處理器型別
我們知道CPU 分為32位、34位,但是,它是如何運作的呢?

想象一下我們有一個 64 位的 CPU,每個時鐘周期傳輸 64 位資料的能力,
時鐘周期是CPU處理一個資訊需要多少時間,CPU 32位在1個周期內轉換
4位元組資料,CPU 64位在1個周期內轉換8位元組資料(32位= 4位元組,64位= 8位元組)
上面我們定義的EmployeeStruct結構體,并且計算得到了每個欄位在記憶體中占用的位元組數,下面我們看CPU處理資訊需要多少時間呢?
先來看下面的一張圖:

圖里面6個周期,每個周期有八個盒子,表示是CPU處理能力,為 8 位元組
-
周期1
第一個屬性是IsPublic,資料型別為布爾型,bool的大小為1 個位元組,因此,當前周期 1 由屬性IsPublic(bool ~ 1 byte)填充,
下一個屬性是Age,資料型別為int64,int64的大小是8位元組,由于第1個周期的剩余記憶體大小只有7個位元組,因此第1個周期無法填充Age屬性,因此,會進入第2個周期,但是,“剩余的空間呢,怎么辦?”, -
周期2
第2個周期由Age屬性填充,資料型別為int64,大小為8位元組,剛好填充滿, -
周期3
第三個屬性Status,資料型別為bool,大小為1位元組,填充(bool~1 byte),剩余記憶體大小為7位元組,然后,下一個屬性是Name,型別為字串,大小為16 位元組,與周期1的情況相同,因為沒有足夠的空間容納下一個屬性,所以將在下一個周期中進入,所以意味著有7個位元組的記憶體被浪費了, -
周期 4 和周期 5
第四個是Name,資料型別為字串,大小為16位元組,從圖上面看,它將在兩個周期中填充,周期 4 中填充 8 個位元組,周期 5 中填充 8 個位元組, -
周期6
最后一個屬性是Image, 資料型別為float32,大小為4位元組,浪費剩余的4 個位元組,
最后通過計算統計:
總時鐘周期 = 6 個時鐘周期
結構體大小 = 48 位元組
浪費的總記憶體 = 18 位元組
所以我們在開發的時候,如果對于一個比較大的資料結構體來說,可能會使結構體的大小變得更大,
那么,如何解決呢?
實際上我們可以根據資料型別的大小來組成序列,最簡單的方法是:
按元素記憶體大小的降序排列欄位
type EmployeeStruct struct {
Name string
Age int64
Image float32
IsPublic bool
Status bool
}
這個時候我們再來看一下時間周期:

-
周期 1 和周期 2
第一個屬性是Name,資料型別為字串,大小為16位元組,因此,它將在兩個周期中填充,周期 1 中填充 8 個位元組,周期 2 中填充 8 個位元組, -
周期3
第3個周期由Age屬性填充,資料型別為int64,大小為8位元組 -
周期4
下一個屬性是Image,資料型別為float32,大小為4位元組,因此,當前周期 4 由屬性Image ( float32 ~ 4 位元組)填充,剩余大小為 4 位元組,
下一個屬性是IsPublic(bool ~ 1 位元組)和 Status(bool ~ 1 位元組),因為最后兩個屬性的總大小只有2個位元組,所以我們可以將其放在回圈4中,這樣一來,回圈4就被Image ( float32 ~ 4位元組)、IsPublic (bool ~ 1位元組)、Status(bool~1 位元組)填滿了,僅浪費 2 位元組記憶體,
最后通過計算統計:
總時鐘周期 = 4 個時鐘周期
結構體大小 = 32 位元組
浪費的總記憶體 = 2 位元組
package main
import (
"fmt"
"unsafe"
)
type EmployeeStruct struct {
Name string
Age int64
Image float32
IsPublic bool
Status bool
}
func main() {
var employee EmployeeStruct
fmt.Println(unsafe.Sizeof(employee)) // output: 32
}
結束
所以我們在開發的時候,重新排序結構欄位是可以提高應用程式的記憶體使用率和運行速度的,
轉載:風向閱讀 - Golang 開發技巧 - 簡單的資料對齊可提高程式速度和記憶體使用率
地址:https://www.aiweimeng.top/archives/56.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556219.html
標籤:其他
下一篇:返回列表
