1. 程式人生 > 其它 >極客兔兔部落格筆記-GO語言高效能程式設計-常用資料結構

極客兔兔部落格筆記-GO語言高效能程式設計-常用資料結構

常用資料結構中的效能優化/陷阱

參考部落格:極客兔兔

字串拼接方法的比較

  • strings.Builder和+
func builderConcat(n int,str string) string {
    var builder strings.Builder
    for i := 0;i<n;i++{
        builder.WriteString(str)
    }
    return builder.String()
}

當時用+拼接2個字串時候是開闢一段新的空間。而strings.Builder,bytes.Buffer,包括切片的[]byte的記憶體是以倍數申請的。當一萬個字串拼接時,strings.Builder方法的記憶體消耗大概是+的記憶體消耗的千分之一。

slice的效能及陷阱

當silce的容量較小時記憶體是以2的倍數擴大的,當達到2048時採用新的策略,避免記憶體申請過大,導致浪費。

切片的結構:

struct {
    ptr *[]T
    len int
    cap int
}

效能缺陷:在已有切片的基礎上進行切片,不會建立新的底層陣列,因為原來的底層資料沒有發生變化,記憶體會一直佔用,直到沒有變數引用該陣列。推薦:用copy代替re-slice //[x:x]

當copy時,切片建立一個新的底層切片,當原切片的底層陣列沒有引用時記憶體就會被GC。

for和range的效能比較

range可以很方便地去遍歷陣列、切片、字典和通道。對nil型別,迭代次數為0。對於通道,for迴圈迭代直到通道被關閉。

僅遍歷下標時for和range效能幾乎一樣,同時遍歷下標和值,for的效能大約是range的2000倍。

range 在迭代過程中返回的是迭代值的拷貝,如果每次迭代的元素的記憶體佔用很低,那麼 for 和 range 的效能幾乎是一樣,例如 []int。但是如果迭代的元素記憶體佔用較高,例如一個包含很多屬性的 struct 結構體,那麼 for 的效能將顯著地高於 range,有時候甚至會有上千倍的效能差異。對於這種場景,建議使用 for,如果使用range,建議只迭代下標,通過下標訪問迭代值,這種使用方式和 for 就沒有區別了。如果想使用 range 同時迭代下標和值,則需要將切片/陣列的元素改為指標,才能不影響效能。

Go空結構體struct{}的使用

unsafe.Sizeof可以得到一個數據型別例項所需要佔用的位元組數。

空結構體不佔據記憶體空間,因此可以廣泛作為各種場景下面的佔位符。

有時候使用 channel 不需要傳送任何的資料,只用來通知子協程(goroutine)執行任務,或只用來控制協程併發度。這種情況下,使用空結構體作為佔位符就非常合適了。