最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go內(nèi)存分配之結(jié)構(gòu)體優(yōu)化技巧

 更新時間:2023年11月22日 11:02:04   作者:洛天楓  
這篇文章主要為大家詳細(xì)介紹了Go語言內(nèi)存分配之結(jié)構(gòu)體優(yōu)化技巧的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

在使用Golang進(jìn)行內(nèi)存分配時,我們需要遵循一系列規(guī)則。在深入了解這些規(guī)則之前,我們需要先了解變量的對齊方式。

Golang的unsafe包中有一個函數(shù)Alignof,簽名如下:

func Alignof(x ArbitraryType) uintptr

對于任何類型為v的變量xAlignOf函數(shù)會返回該變量的對齊方式。我們將對齊方式記為m。現(xiàn)在,Golang確保m是滿足變量x的內(nèi)存地址 % m == 0的最大可能數(shù),也就是說,變量x的內(nèi)存地址是m的倍數(shù)。

讓我們來看看一些數(shù)據(jù)類型的對齊方式:

  • byteint8uint8 -> 1
  • int16uint16 -> 2
  • int32uint32float32complex64 -> 4
  • intint64uint64float64complex128 -> 8
  • stringslice -> 8

對于結(jié)構(gòu)體中的字段,行為可能會有所不同,詳細(xì)信息請參考包的文檔。

為了更好地理解結(jié)構(gòu)體內(nèi)存分配的情況,我們將使用unsafe包中的另一個函數(shù)Offsetof。該函數(shù)返回字段相對于結(jié)構(gòu)體起始位置的位置,換句話說,它返回字段起始位置與結(jié)構(gòu)體起始位置之間的字節(jié)數(shù)。

func Offsetof(x ArbitraryType) uintptr

為了更好地理解結(jié)構(gòu)體內(nèi)存分配,讓我們以一個示例結(jié)構(gòu)體為例:

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

現(xiàn)在,我們將找出類型為Example的變量所占用的總內(nèi)存,并嘗試優(yōu)化分配。

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)) // 輸出:0
fmt.Println("字段b的偏移量:", unsafe.Offsetof(v.b)) // 輸出:8
fmt.Println("字段c的偏移量:", unsafe.Offsetof(v.c)) // 輸出:24
fmt.Println("字段d的偏移量:", unsafe.Offsetof(v.d)) // 輸出:28

現(xiàn)在,問題出現(xiàn)了:“為什么結(jié)構(gòu)體中字段b的偏移量是8?它應(yīng)該是1,因為字段a的類型是int8,只占用1個字節(jié)。”回到字符串?dāng)?shù)據(jù)類型的對齊方式,它的值為8,這意味著地址需要被8整除,因此在其中插入了7個字節(jié)的“填充”,以確保這種行為。

為什么字段c的偏移量是24?字段b中的字符串看起來比16個字節(jié)要長得多,如果字符串的偏移量是8,那么字段c的偏移量應(yīng)該更大一些。

上述問題的答案是,在Go中,字符串并不是在結(jié)構(gòu)體內(nèi)的同一位置分配內(nèi)存的。有一個單獨的數(shù)據(jù)結(jié)構(gòu)來保存字符串描述符,并且該字符串描述符以原地方式存儲在結(jié)構(gòu)體中,用于類型為string的字段,該描述符的大小為16個字節(jié)。

現(xiàn)在,讓我們來看看unsafe包中的另一個函數(shù)Sizeof。正如其名稱所示,該函數(shù)估計并返回類型為x的變量所占用的字節(jié)數(shù)。

注意:它是根據(jù)結(jié)構(gòu)體中可能存在的不同大小的字段來估計大小的。

func Sizeof(x ArbitraryType) uintptr

現(xiàn)在,讓我們來看看我們的結(jié)構(gòu)體Example的大小。

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

我們?nèi)绾蝺?yōu)化這個結(jié)構(gòu)體以最小化填充呢?

為了優(yōu)化這個結(jié)構(gòu)體的內(nèi)存,我們將查看不同數(shù)據(jù)類型的對齊方式,并嘗試減少填充。讓我們嘗試將兩個int8類型的字段放在一起。

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

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

太棒了,我們?nèi)サ袅艘恍┨畛洌菫槭裁创笮∪匀皇?2?大小應(yīng)該是1(a)+ 1(c)+ 6(填充)+ 16(b)+ 4(d)= 28

現(xiàn)在,當(dāng)結(jié)構(gòu)體的最后一個字段與架構(gòu)的對齊要求不完全一致時,會在最后一個字段之后添加填充,以確保結(jié)構(gòu)體的整體大小是其字段中最大對齊要求的倍數(shù)。因為字符串?dāng)?shù)據(jù)類型的最大對齊方式為8,所以額外添加了填充,使大小成為8的倍數(shù),即在末尾填充了4個字節(jié),使大小為32字節(jié)。

我們能否進(jìn)一步減少填充,使其更加優(yōu)化?

讓我們嘗試通過移動字段位置來實現(xiàn)。

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

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

我們可以看到,通過重新排列字段的位置,使得對齊需要最小化填充,我們已經(jīng)將結(jié)構(gòu)體的大小從32減小到24,這是內(nèi)存優(yōu)化的巨大進(jìn)步,達(dá)到了25%。

當(dāng)前的內(nèi)存占用是16(b)+ 4(d)+ 1(a)+ 1(b)+ 2(填充)。

遺憾的是,由于語言和架構(gòu)的限制,我們無法進(jìn)一步去除填充。

到此這篇關(guān)于Go內(nèi)存分配之結(jié)構(gòu)體優(yōu)化技巧的文章就介紹到這了,更多相關(guān)Go結(jié)構(gòu)體內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Go語言中獲取文件路徑的不同方法與應(yīng)用場景

    詳解Go語言中獲取文件路徑的不同方法與應(yīng)用場景

    在使用?Go?開發(fā)項目時,估計有不少人遇到過無法正確處理文件路徑的問題,本文將嘗試從簡單到復(fù)雜,詳細(xì)介紹?Go?中獲取路徑的不同方法及應(yīng)用場景,希望對大家有所幫助
    2024-02-02
  • 讓GPT教你用go語言和C語言開發(fā)IDE配置學(xué)習(xí)

    讓GPT教你用go語言和C語言開發(fā)IDE配置學(xué)習(xí)

    這篇文章主要介紹了讓GPT教你用go語言和C語言開發(fā)IDE配置學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 解決GO編譯時避免引入外部動態(tài)庫的問題

    解決GO編譯時避免引入外部動態(tài)庫的問題

    最近碰到一個問題,有一個流量采集的組件中使用到了github.com/google/gopacket 這個庫,這個庫使用一切正常,但是唯獨有一個缺點,編譯后的二進(jìn)制文件依賴于libpcap.so的動態(tài)庫,這篇文章主要介紹了GO編譯時避免引入外部動態(tài)庫的解決方法,需要的朋友可以參考下
    2022-10-10
  • 在Go語言中使用JSON的方法

    在Go語言中使用JSON的方法

    這篇文章主要介紹了在Go語言中使用JSON的相關(guān)資料,需要的朋友可以參考下
    2018-02-02
  • Go?channel實現(xiàn)批量讀取數(shù)據(jù)

    Go?channel實現(xiàn)批量讀取數(shù)據(jù)

    Go中的?channel?其實并沒有提供批量讀取數(shù)據(jù)的方法,需要我們自己實現(xiàn)一個,使用本文就來為大家大家介紹一下如何通過Go?channel實現(xiàn)批量讀取數(shù)據(jù)吧
    2023-12-12
  • 基于Go語言編寫一個能在Windows上錄音的小程序

    基于Go語言編寫一個能在Windows上錄音的小程序

    這篇文章主要為大家詳細(xì)介紹了如何基于Go語言編寫一個能在Windows上錄音的小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2026-03-03
  • Golang監(jiān)聽日志文件并發(fā)送到kafka中

    Golang監(jiān)聽日志文件并發(fā)送到kafka中

    這篇文章主要介紹了Golang監(jiān)聽日志文件并發(fā)送到kafka中,日志收集項目的準(zhǔn)備中,本文主要講的是利用golang的tail庫,監(jiān)聽日志文件的變動,將日志信息發(fā)送到kafka中?,需要的朋友可以參考一下
    2022-04-04
  • go語言接口之接口值舉例詳解

    go語言接口之接口值舉例詳解

    接口是一種抽象類型,是對其他類型行為的概括與抽象,從語法角度來看,接口是一組方法定義的集合,下面這篇文章主要給大家介紹了關(guān)于go語言接口之接口值的相關(guān)資料,文章通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • 一文帶你掌握掌握 Golang結(jié)構(gòu)體與方法

    一文帶你掌握掌握 Golang結(jié)構(gòu)體與方法

    在 Golang 中,結(jié)構(gòu)體和方法是實現(xiàn)面向?qū)ο缶幊痰闹匾M成部分,也是 Golang 的核心概念之一。在本篇文章中,我們將深入介紹 Golang 結(jié)構(gòu)體與方法的概念、使用方法以及相關(guān)的編程技巧和最佳實踐
    2023-04-04
  • Go高級特性探究之處理1分鐘百萬請求詳解

    Go高級特性探究之處理1分鐘百萬請求詳解

    對于大型的互聯(lián)網(wǎng)應(yīng)用程序,如電商平臺、社交網(wǎng)絡(luò)、金融交易平臺等,每秒鐘都會收到大量的請求,那么Go是如何處理這些百萬請求的呢,下面就來和大家詳細(xì)講講
    2023-06-06

最新評論

卓资县| 丹江口市| 兴宁市| 定远县| 积石山| 朝阳区| 永兴县| 洞头县| 建宁县| 图木舒克市| 紫金县| 台中县| 偏关县| 铜山县| 古浪县| 安国市| 迁安市| 成武县| 临颍县| 云浮市| 肇东市| 浑源县| 泗洪县| 宜阳县| 凉山| 石林| 井陉县| 抚远县| 隆尧县| 获嘉县| 广河县| 青田县| 都安| 石阡县| 盱眙县| 酉阳| 乾安县| 那坡县| 乌审旗| 利津县| 双峰县|