您好,登錄后才能下訂單哦!
這篇文章主要講解了“Go語言是否有必要內存對齊”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Go語言是否有必要內存對齊”吧!
有些同學可能不知道,struct 中的字段順序不同,內存占用也有可能會相差很大。比如:
type T1 struct { a int8 b int64 c int16 } type T2 struct { a int8 c int16 b int64 }
在 64 bit 平臺上,T1 占用 24 bytes,T2 占用 16 bytes 大小;而在 32 bit 平臺上,T1 占用 16 bytes,T2 占用 12 bytes 大小。可見不同的字段順序,最終決定 struct 的內存大小,所以有時候合理的字段順序可以減少內存的開銷。
這是為什么呢?因為有內存對齊的存在,編譯器使用了內存對齊,那么最后的大小結果就會不一樣。至于為什么要做對齊,主要考慮下面兩個原因:
平臺(移植性)
不是所有的硬件平臺都能夠訪問任意地址上的任意數據。例如:特定的硬件平臺只允許在特定地址獲取特定類型的數據,否則會導致異常情況
性能
若訪問未對齊的內存,將會導致 CPU 進行兩次內存訪問,并且要花費額外的時鐘周期來處理對齊及運算。而本身就對齊的內存僅需要一次訪問就可以完成讀取動作,這顯然高效很多,是標準的空間換時間做法
有的小伙伴可能會認為內存讀取,就是一個簡單的字節數組擺放。但實際上 CPU 并不會以一個一個字節去讀取和寫入內存,相反 CPU 讀取內存是一塊一塊讀取的,塊的大小可以為 2、4、6、8、16 字節等大小,塊大小我們稱其為內存訪問粒度。假設訪問粒度為 4,那么 CPU 就會以每 4 個字節大小的訪問粒度去讀取和寫入內存。
在不同平臺上的編譯器都有自己默認的 “對齊系數”。一般來講,我們常用的 x86 平臺的系數為 4;x8664 平臺系數為 8。需要注意的是,除了這個默認的對齊系數外,還有不同數據類型的對齊系數。數據類型的對齊系數在不同平臺上可能會不一致。例如,在 x8664 平臺上,int64 的對齊系數為 8,而在 x86 平臺上其對齊系數就是 4。
還是拿上面的 T1、T2 來說,在 x86_64 平臺上,T1 的內存布局為:
T2 的內存布局為(int16 的對齊系數為 2):
仔細看,T1 存在許多 padding,顯然它占據了不少空間。那么也就不難理解,為什么調整結構體內成員變量的字段順序就能達到縮小結構體占用大小的疑問了,是因為巧妙地減少了 padding 的存在。讓它們更 “緊湊” 了。
其實內存對齊除了可以降低內存占用之外,還有一種情況是必須要手動對齊的:在 x86 平臺上原子操作 64bit 指針。之所以要強制對齊,是因為在 32bit 平臺下進行 64bit 原子操作要求必須 8 字節對齊,否則程序會 panic。
感謝各位的閱讀,以上就是“Go語言是否有必要內存對齊”的內容了,經過本文的學習后,相信大家對Go語言是否有必要內存對齊這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。