Golang性能優(yōu)化的技巧分享
一.簡(jiǎn)介
? 性能優(yōu)化的前提是滿(mǎn)足正確可靠、簡(jiǎn)潔清晰等質(zhì)量因素。性能優(yōu)化是綜合評(píng)估,有時(shí)候時(shí)間效率和空間效率可能對(duì)立。針對(duì) Go語(yǔ)言特性,下文介紹 Go 相關(guān)的性能優(yōu)化建議。
二.性能優(yōu)化建議
1.Benchmark
Benchmark能夠?yàn)镚o語(yǔ)言提供支持基準(zhǔn)性能測(cè)試,能夠提供實(shí)際的數(shù)據(jù)衡量。通過(guò)go test -bench=. -benchmen命令進(jìn)行基準(zhǔn)性能測(cè)試。
// from fib.go func Fib(n int) int { if n <2{ return n } return Fib(n-1) + Fib(n-2) } // from fib_test.go func BenchmarkFib10(b *testing.B) { // run the Fib function b.N times for n := 0; n < b.N; n++{ Fib(10) } }
結(jié)果說(shuō)明:
第四行第一個(gè)結(jié)果表示BenchmarkFib10是測(cè)試函數(shù)名8 表示GOMAXPROCS的值為8,第四行第二個(gè)結(jié)果表示一共執(zhí)行1855870次即b.N的值,第四行第三個(gè)結(jié)果表示每次執(zhí)行花費(fèi)602.5ns,第四行第四個(gè)結(jié)果表示每次執(zhí)行申請(qǐng)多大的內(nèi)存,第四行第五個(gè)結(jié)果表示每次執(zhí)行申請(qǐng)的幾次內(nèi)存。
2.slice
? slice可以預(yù)分配內(nèi)存,使用make() 初始化切片時(shí)提供容量信息。
func NoPreAlloc( size int) { data := make([]int, 0) for k := 0; k < size; k++ { data = append( data, k ) } } func PreAlloc(size int) { data := make([]int, 0, size ) for k := 0; k < size; k++ { data = append( data, k ) } }
實(shí)驗(yàn)結(jié)果:
切片本質(zhì)是一個(gè)數(shù)組片段的描述包括數(shù)組指針,片段的長(zhǎng)度,片段的容量(不改變內(nèi)存分配情況下的最大長(zhǎng)度)。切片操作并不復(fù)制切片指向的元素,創(chuàng)建一個(gè)新的切片會(huì)復(fù)用原來(lái)切片的底層數(shù)組。
3.map
map預(yù)分配內(nèi)存
func NoPreAlloc(size int) { data := make(map[int]int ) for i := 0; i < size; i++ { data[i] = 1 } } func PreAlloc(size int) { data := make(map[int]int, size) for i := 0; i < size; i++{ data[i] = 1 } }
實(shí)驗(yàn)結(jié)果:
不斷向 map 中添加元素的操作會(huì)觸發(fā) map 的擴(kuò)容,提前分配好空間可以減少內(nèi)存拷貝和 Rehash 的消耗,根據(jù)實(shí)際需求提前預(yù)估好需要的空間。
4.字符串處理
使用strings.Builder
func ByteBuffer(n int, str string) string { buf := new( bytes .Buffer) for i := 0;i < n; i++ { buf.writeString(str) } return buf.String() }
實(shí)驗(yàn)結(jié)果:
使用 +字符串拼接性能最差,strings.Builder,bytes.Buffer 相近,strings.Buffer 更快。字符串在 Go語(yǔ)言中是不可變類(lèi)型,占用內(nèi)存大小是固定的。使用 + 每次都會(huì)重新分配內(nèi)存。strings.Builder,bytes.Buffer 底層都是 []byte 數(shù)組。內(nèi)存擴(kuò)容策略不需要每次拼接重新分配內(nèi)存。
5.空結(jié)構(gòu)體
空結(jié)構(gòu)體 struct{}實(shí)例不占據(jù)任何的內(nèi)存空間??勺鳛楦鞣N場(chǎng)景下的占位符使用,節(jié)省資源,空結(jié)構(gòu)體本身具備很強(qiáng)的語(yǔ)義,即這里不需要任何值,僅作為占位符。
func EmptyStructMap(n int) { m := make(map[int]struct{}) for i := 0;i < n; i++ { m[i] = struct{}{} } } func BoolMap(n int) { m := make(map[int]bool) for i := 0;i < n; i++ { m[i] = false } }
實(shí)驗(yàn)結(jié)果:
實(shí)現(xiàn) Set,可以考慮用 map 來(lái)代替。對(duì)于這個(gè)場(chǎng)景,只需要用到 map 的鍵,而不需要值。即使是將 map 的值設(shè)置為 bool 類(lèi)型,也會(huì)多占據(jù) 1個(gè)字節(jié)空間。
6.atomic
使用atomic包
type atomicCounter struct { i int32 } func AtomicAddOne( c *atomicCounter) { atomic.AddInt32( &c.i, 1) } type mutexCounter struct { i int32 m sync.Mutex } func MutexAddOne(c *mutexCounter) { c.m.Lock() c.i+ c.m.Unlock() }
實(shí)驗(yàn)結(jié)果:
鎖的實(shí)現(xiàn)是通過(guò)操作系統(tǒng)來(lái)實(shí)現(xiàn),屬于系統(tǒng)調(diào)用。atomic 操作是通過(guò)硬件實(shí)現(xiàn),效率比鎖高。sync.Mutex 應(yīng)該用來(lái)保護(hù)一段邏輯,不僅僅用于保護(hù)一個(gè)變量。對(duì)于非數(shù)值操作,可以使用 atomic.Value,能承載一個(gè)interface。
三.小結(jié)
避免常見(jiàn)的性能陷阱可以保證大部分程序的性能。普通應(yīng)用代碼,不要一味地追求程序的性能。越高級(jí)的性能優(yōu)化手段越容易出現(xiàn)問(wèn)題。在滿(mǎn)足正確可靠、簡(jiǎn)潔清晰的質(zhì)量要求的前提下提高程序性能。
到此這篇關(guān)于Golang性能優(yōu)化的技巧分享的文章就介紹到這了,更多相關(guān)Go性能優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go-家庭收支記賬軟件項(xiàng)目實(shí)現(xiàn)
這篇文章主要介紹了Go-家庭收支記賬軟件項(xiàng)目實(shí)現(xiàn),本文章內(nèi)容詳細(xì),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,需要的朋友可以參考下2023-01-01以alpine作為基礎(chǔ)鏡像構(gòu)建Golang可執(zhí)行程序操作
這篇文章主要介紹了以alpine作為基礎(chǔ)鏡像構(gòu)建Golang可執(zhí)行程序操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12CSP communicating sequential processes并發(fā)模型
這篇文章主要為大家介紹了CSP communicating sequential processes并發(fā)模型,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Golang 空map和未初始化map的注意事項(xiàng)說(shuō)明
這篇文章主要介紹了Golang 空map和未初始化map的注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04Go語(yǔ)言L(fǎng)eetCode500鍵盤(pán)行題解示例詳解
這篇文章主要為大家介紹了Go語(yǔ)言L(fǎng)eetCode500鍵盤(pán)行題解示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例
這篇文章主要介紹了Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05