golang slice效能分析

hatlonely發表於2018-01-26

golang在gc這塊的做得比較弱,頻繁地申請和釋放記憶體會消耗很多的資源。另外slice使用陣列實現,有一個容量和長度的問題,當slice的容量用完再繼續新增元素時需要擴容,而這個擴容會把申請新的空間,把老的內容複製到新的空間,這是一個非常耗時的操作。有兩種方式可以減少這個問題帶來的效能開銷:

  1. 在slice初始化的時候設定capacity(但更多的時候我們可能並不知道capacity的大小)
  2. 複用slice

下面就針對這兩個優化設計瞭如下的benchmark,程式碼在: https://github.com/hatlonely/hellogolang/blob/master/internal/buildin/slice_test.go

BenchmarkAppendWithoutCapacity-8                     100      21442390 ns/op
BenchmarkAppendWithCapLessLen10th-8                  100      18579700 ns/op
BenchmarkAppendWithCapLessLen3th-8                   100      13867060 ns/op
BenchmarkAppendWithCapEqualLen-8                     200       6287940 ns/op
BenchmarkAppendWithCapGreaterLen10th-8               100      18692880 ns/op
BenchmarkAppendWithoutCapacityReuse-8                300       5014320 ns/op
BenchmarkAppendWithCapEqualLenReuse-8                300       4821420 ns/op
BenchmarkAppendWithCapGreaterLen10thReuse-8          300       4903230 ns/op

主要結論:

  1. 在已知 capacity 的情況下,直接設定 capacity 減少記憶體的重新分配,有效提高效能
  2. capacity < length,capacity越接近length,效能越好
  3. capacity > lenght,如果太大,反而會造成效能下降,這裡當capacity > 10 * length時,與不設定capacity的效能差不太多
  4. 多次使用複用同一塊記憶體能有效提高效能

相關文章