日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Golang數(shù)據(jù)結(jié)構(gòu)性能優(yōu)化實(shí)踐

如果你有Golang開發(fā)經(jīng)驗(yàn),一定定義過struct類型。

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、元謀ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的元謀網(wǎng)站制作公司

但可能你不知道,通過簡(jiǎn)單的重新排序struct字段,可以極大提高Go程序的速度和內(nèi)存使用效率!

是不是難以置信?我們一起來看一下吧!

簡(jiǎn)單Demo

type BadStruct struct {
 age         uint8
 passportNum uint64
 siblings    uint16
}

type GoodStruct struct {
 age         uint8
 siblings    uint16
 passportNum uint64
}

在上面的代碼片段中,我們創(chuàng)建了兩個(gè)具有相同字段的結(jié)構(gòu)體。然后編寫一個(gè)簡(jiǎn)單程序分別輸出其內(nèi)存使用情況。

// Output
Bad struct is 24 bytes long
Good struct is 16 bytes long

如你所見,它們?cè)趦?nèi)存使用方面并不一樣。

是什么原因?qū)е聝蓚€(gè)完全相似的struct消耗的內(nèi)存不同?

答案在于數(shù)據(jù)在計(jì)算機(jī)內(nèi)存中的排列方式。

簡(jiǎn)而言之,數(shù)據(jù)結(jié)構(gòu)對(duì)齊。

數(shù)據(jù)結(jié)構(gòu)對(duì)齊

CPU以字(word)為單位讀取數(shù)據(jù),而不是字節(jié)(byte)。

64位系統(tǒng)中,一個(gè)word是8個(gè)字節(jié),而32位系統(tǒng)中,一個(gè)word是4個(gè)字節(jié)。

簡(jiǎn)而言之,CPU以其字長(zhǎng)的倍數(shù)讀取內(nèi)存地址。

想象一下,在64位系統(tǒng)中,為了獲取變量passportNum,CPU需要兩個(gè)周期來訪問數(shù)據(jù)。

第一個(gè)周期將獲取內(nèi)存的0到7字節(jié),下一個(gè)周期獲取其余內(nèi)存字節(jié)。

把它想象成一個(gè)筆記本,每頁只能存儲(chǔ)一個(gè)字大小的數(shù)據(jù)(在本例中為8字節(jié))。如果passportNum分散在兩個(gè)頁,則需要兩次讀取才能檢索到完整的數(shù)據(jù)。

非常低效。

因此需要數(shù)據(jù)結(jié)構(gòu)對(duì)齊,讓計(jì)算機(jī)將數(shù)據(jù)存儲(chǔ)在等于數(shù)據(jù)大小倍數(shù)的地址上。

4字節(jié)數(shù)據(jù)只能從內(nèi)存地址0或4開始

例如,2字節(jié)數(shù)據(jù)可以存儲(chǔ)在內(nèi)存0、2或4中,而4字節(jié)數(shù)據(jù)可以存儲(chǔ)在內(nèi)存0、4或8中。

通過簡(jiǎn)單的對(duì)齊數(shù)據(jù),計(jì)算機(jī)確??梢栽谝粋€(gè)CPU周期內(nèi)檢索到變量passportNum。

數(shù)據(jù)結(jié)構(gòu)填充

填充是實(shí)現(xiàn)數(shù)據(jù)對(duì)齊的關(guān)鍵。

計(jì)算機(jī)通過在數(shù)據(jù)結(jié)構(gòu)之間填充額外的字節(jié),從而對(duì)齊字段。

這就是額外內(nèi)存的來源!

我們來回顧一下BadStruct和GoodStruct。

GoodStruct消耗更少的內(nèi)存,僅僅因?yàn)榕cBadStruct相比,其struct字段順序更合理。

由于填充,兩個(gè)13字節(jié)的數(shù)據(jù)結(jié)構(gòu)分別變成了16字節(jié)和24字節(jié)。

因此,可以僅僅通過對(duì)struct字段重新排序來節(jié)省額外的內(nèi)存!

這種優(yōu)化為什么重要?

問題來了,你為什么要關(guān)心這個(gè)?

兩個(gè)方面,速度和內(nèi)存使用。

我們做一個(gè)簡(jiǎn)單的基準(zhǔn)測(cè)試來證明!

func traverseGoodStruct() uint16 {
 var arbitraryNum uint16
  
 for _, goodStruct := range GoodStructArr {
  arbitraryNum += goodStruct.siblings
 }
  
 return arbitraryNum
}

func traverseBadStruct() uint16 {
 var arbitraryNum uint16
  
 for _, badStruct := range BadStructArr {
  arbitraryNum += badStruct.siblings
 }
  
 return arbitraryNum
}

func BenchmarkTraverseGoodStruct(b *testing.B) {
 for n := 0; n < b.N; n++ {
  traverseGoodStruct()
 }
}

func BenchmarkTraverseBadStruct(b *testing.B) {
 for n := 0; n < b.N; n++ {
  traverseBadStruct()
 }
}

對(duì)GoodStruct和BadStruct進(jìn)行基準(zhǔn)測(cè)試的方法是循環(huán)遍歷數(shù)組,并將struct字段累加到變量中。

從結(jié)果中可以看出,遍歷GoodStruct確實(shí)比BadStruct花費(fèi)時(shí)間更少。

對(duì)struct字段重排序可以優(yōu)化應(yīng)用程序的內(nèi)存使用和速度。

想象一下,維護(hù)一個(gè)具有大量結(jié)構(gòu)體的大型應(yīng)用程序,改變將會(huì)更為明顯。

結(jié)語

好了,全文到此為止,我們以一個(gè)簡(jiǎn)單的行動(dòng)呼吁來結(jié)束:一定要對(duì)struct結(jié)構(gòu)字段進(jìn)行重排序!


本文標(biāo)題:Golang數(shù)據(jù)結(jié)構(gòu)性能優(yōu)化實(shí)踐
網(wǎng)站地址:http://www.dlmjj.cn/article/dpdpgcc.html