日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Golang优化之内存对齐

發布時間:2023/12/20 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Golang优化之内存对齐 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前文

話說今天在用uintptr進行指針運算的時候,突然想起來有個內存對齊的東西,那么對這個uintptr計算是否會有影響?

帶著疑問,開始吧。

你將獲得以下知識點:
1.什么是內存對齊?
2.為什么需要內存對齊?
3.如何進行內存對齊?
4.golang的內存對齊如何體現?
5.如何利用內存對齊來優化golang?

正文

1.什么是內存對齊?

在想象中內存應該是一個一個獨立的字節組成的。像這樣:

事實上,人家是這樣的:

內存是按照成員的聲明順序,依次分配內存,第一個成員偏移量是0,其余每個成員的偏移量為指定數的整數倍數(圖中是4)。像這樣進行內存的分配叫做內存對齊。

2.為什么需要內存對齊?

原因有兩點:

平臺原因

并不是所有的硬件平臺都能訪問任意地址上的任意數據,會直接報錯的!
(解釋:比如說有的cpu讀取4個字節數據,要是沒有內存對齊,從1開始那么內存就需要把0-7字節的全部取出來,再剔除掉1/5/6/7,增加了額外的操作,cpu不一定能這么搞,自然就報錯了)

性能原因

訪問未對齊的內存,需要訪問兩次;如果對齊的話就只需要一次了。
(解釋:比如取int64,按照8個位對齊好了,那獲取的話直接就是獲取8個字節就好了,邊界好判斷)

3.如何進行內存對齊?

二個原則:
1.具體類型,對齊值=min(編譯器默認對齊值,類型大小Sizeof長度)
2.struct每個字段內部對齊,對齊值=min(默認對齊值,字段最大類型長度)

4.golang的內存對齊如何體現?

4.1 結構體的相同成員不同順序

結構體是平時寫代碼經常用到的。相同的成員,不同的排列順序,會有什么區別嗎?

舉個例子:

func main() {fmt.Println(unsafe.Sizeof(struct {i8 int8i16 int16i32 int32}{}))fmt.Println(unsafe.Sizeof(struct {i8 int8i32 int32i16 int16}{})) }

輸出:

8 12

what?竟然不一樣。
分析一波:需要內存對齊的話,因為最大是int32,所以最終記過必須是4個字節的倍數才能對齊。
當8-16-32的時候,類似這樣|x-xx|xxxx|。
當8-32-16的時候,類似這樣|x—|xxxx|xx–|。
一眼就看出了大小了。

這里的為什么是x-xx而不是xxx-需要說明下。因為當int8放入內存的時候,其占坑1個字節,對齊值為1,而int16占坑2個字節,對齊值為2,所以說會先偏移2個字節從第三個字節才開始放int16的數

4.2指針運算

現在對結構體Test通過指針計算的方式進行賦值。
Test內存情況:|x-xx|xxxx|。需要注意的是這里的“-”需要多計算一個字節才行。

type Test struct {i8 int8i16 int16i32 int32 }func main() {var t = new(Test)// 從0開始var i8 = (*int8)(unsafe.Pointer(t))*i8 = int8(10)// 偏移int8+1的字節數,注意這里有個1!!! var i16 = (*int16)(unsafe.Pointer(uintptr(unsafe.Pointer(t))+ uintptr(1) + uintptr(unsafe.Sizeof(int8(0)))))*i16 = int16(10)// 偏移int8+1+int16+的字節數,注意這里有個1!!! var i32 = (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) + uintptr(1) + uintptr(unsafe.Sizeof(int8(0))+uintptr(unsafe.Sizeof(int16(0))))))*i32 = int32(10)fmt.Println(*t) }

輸出:

{10 10 10}

附上兩個神器:

功能函數
獲取對齊值unsafe.Alignof(t.i16)
獲取偏移值unsafe.Offsetof(t.i16)

5.如何利用內存對齊來優化golang?

5.1 結構體占用內存過大的問題

根據計算對齊值進行成員順序的拼湊,可以一定程度上縮小結構體占用的內存。

5.2 指針運算的坑

通過分析偏移量和對齊值,準確計算每個成員所偏移的位數,避免算錯。

延伸閱讀

Go語言實戰筆記(二十六)| Go unsafe 包之內存布局

如果你覺得有收獲~可以關注我的公眾號【咖啡色的羊駝】~第一時間收到我的分享和知識梳理~

總結

以上是生活随笔為你收集整理的Golang优化之内存对齐的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。