日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Go 內存分配:結構體中的優化技巧

來源: 責編: 時間:2023-11-21 09:38:46 232觀看
導讀在使用Golang進行內存分配時,我們需要遵循一系列規則。在深入了解這些規則之前,我們需要先了解變量的對齊方式。Golang的unsafe包中有一個函數Alignof,簽名如下:func Alignof(x ArbitraryType) uintptr對于任何類型為v的

在使用Golang進行內存分配時,我們需要遵循一系列規則。在深入了解這些規則之前,我們需要先了解變量的對齊方式。iG428資訊網——每日最新資訊28at.com

Golang的unsafe包中有一個函數Alignof,簽名如下:iG428資訊網——每日最新資訊28at.com

func Alignof(x ArbitraryType) uintptr

對于任何類型為v的變量x,AlignOf函數會返回該變量的對齊方式。我們將對齊方式記為m。現在,Golang確保m是滿足變量x的內存地址 % m == 0的最大可能數,也就是說,變量x的內存地址是m的倍數。iG428資訊網——每日最新資訊28at.com

讓我們來看看一些數據類型的對齊方式:iG428資訊網——每日最新資訊28at.com

  • byte, int8, uint8 -> 1
  • int16, uint16 -> 2
  • int32, uint32, float32, complex64 -> 4
  • int, int64, uint64, float64, complex128 -> 8
  • string, slice -> 8

對于結構體中的字段,行為可能會有所不同,詳細信息請參考包的文檔。iG428資訊網——每日最新資訊28at.com

為了更好地理解結構體內存分配的情況,我們將使用unsafe包中的另一個函數Offsetof。該函數返回字段相對于結構體起始位置的位置,換句話說,它返回字段起始位置與結構體起始位置之間的字節數。iG428資訊網——每日最新資訊28at.com

func Offsetof(x ArbitraryType) uintptr

為了更好地理解結構體內存分配,讓我們以一個示例結構體為例:iG428資訊網——每日最新資訊28at.com

type Example struct {    a int8    b string    c int8    d int32}

現在,我們將找出類型為Example的變量所占用的總內存,并嘗試優化分配。iG428資訊網——每日最新資訊28at.com

var v = Example{    a: 10,    b: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rhoncus.",    c: 20,    d: 100,}fmt.Println("字段a的偏移量:", unsafe.Offsetof(v.a)) // 輸出:0fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 輸出:8fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 輸出:24fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 輸出:28

現在,問題出現了:“為什么結構體中字段b的偏移量是8?它應該是1,因為字段a的類型是int8,只占用1個字節。”回到字符串數據類型的對齊方式,它的值為8,這意味著地址需要被8整除,因此在其中插入了7個字節的“填充”,以確保這種行為。iG428資訊網——每日最新資訊28at.com

為什么字段c的偏移量是24?字段b中的字符串看起來比16個字節要長得多,如果字符串的偏移量是8,那么字段c的偏移量應該更大一些。iG428資訊網——每日最新資訊28at.com

上述問題的答案是,在Go中,字符串并不是在結構體內的同一位置分配內存的。有一個單獨的數據結構來保存字符串描述符,并且該字符串描述符以原地方式存儲在結構體中,用于類型為string的字段,該描述符的大小為16個字節。iG428資訊網——每日最新資訊28at.com

現在,讓我們來看看unsafe包中的另一個函數Sizeof。正如其名稱所示,該函數估計并返回類型為x的變量所占用的字節數。iG428資訊網——每日最新資訊28at.com

注意:它是根據結構體中可能存在的不同大小的字段來估計大小的。iG428資訊網——每日最新資訊28at.com

func Sizeof(x ArbitraryType) uintptr

現在,讓我們來看看我們的結構體Example的大小。iG428資訊網——每日最新資訊28at.com

fmt.Println("Example的大小:", unsafe.Sizeof(v)) // 輸出:32

我們如何優化這個結構體以最小化填充呢?iG428資訊網——每日最新資訊28at.com

為了優化這個結構體的內存,我們將查看不同數據類型的對齊方式,并嘗試減少填充。讓我們嘗試將兩個int8類型的字段放在一起。iG428資訊網——每日最新資訊28at.com

type y struct {    a int8    c int8    b string    d int32}var v = y{}fmt.Println("字段a的偏移量:", unsafe.Offsetof(v.a)) // 輸出:0fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 輸出:8fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 輸出:1fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 輸出:24fmt.Println("Example的大小:", unsafe.Sizeof(v)) // 輸出:32

太棒了,我們去掉了一些填充,但是為什么大小仍然是32?大小應該是1(a)+ 1(c)+ 6(填充)+ 16(b)+ 4(d)= 28iG428資訊網——每日最新資訊28at.com

現在,當結構體的最后一個字段與架構的對齊要求不完全一致時,會在最后一個字段之后添加填充,以確保結構體的整體大小是其字段中最大對齊要求的倍數。因為字符串數據類型的最大對齊方式為8,所以額外添加了填充,使大小成為8的倍數,即在末尾填充了4個字節,使大小為32字節。iG428資訊網——每日最新資訊28at.com

我們能否進一步減少填充,使其更加優化?iG428資訊網——每日最新資訊28at.com

讓我們嘗試通過移動字段位置來實現。iG428資訊網——每日最新資訊28at.com

type y struct {    b string    d int32    a int8    c int8}var v = y{}fmt.Println("字段a的偏移量:", unsafe.Offsetof(v.a)) // 輸出:20fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 輸出:0fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 輸出:21fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 輸出:16fmt.Println("Example的大小:", unsafe.Sizeof(v)) // 輸出:24

我們可以看到,通過重新排列字段的位置,使得對齊需要最小化填充,我們已經將結構體的大小從32減小到24,這是內存優化的巨大進步,達到了25%。iG428資訊網——每日最新資訊28at.com

當前的內存占用是16(b)+ 4(d)+ 1(a)+ 1(b)+ 2(填充)。iG428資訊網——每日最新資訊28at.com

遺憾的是,由于語言和架構的限制,我們無法進一步去除填充。iG428資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-32009-0.htmlGo 內存分配:結構體中的優化技巧

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 分布式進階-鏈路追蹤SpringCloudSleuth、Zipkin【實戰篇】

下一篇: 函數組件和函數式編程有關系么?

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 高陵县| 房山区| 建德市| 万州区| 五指山市| 如东县| 义乌市| 师宗县| 临湘市| 公安县| 建宁县| 垣曲县| 沾益县| 乌兰县| 团风县| 山阴县| 阳东县| 家居| 富宁县| 尚义县| 炎陵县| 南华县| 丰镇市| 长泰县| 浦城县| 诏安县| 高尔夫| 平顺县| 确山县| 印江| 高青县| 东安县| 灌阳县| 郴州市| 胶南市| 安图县| 三原县| 瓮安县| 衡东县| 个旧市| 津南区|