Golang筆記-基準測試

上一篇寫了些簡單的單元測試,這一篇來看看go中的基準測試。在go中基準測試也是開箱即用的。使用testing.B結構對象。linux

須要測試的代碼

咱們依然用上一篇的代碼結構
│  main.go
│  main_test.go

main.go

func JoinStrUseSprint(a,b string) string {
    return  fmt.Sprintf("%s%s",a,b)
}

func JoinStrUseNor(a,b string) string {
    return  a+b
}

建立一個基準測試

建立普通單元測試咱們使用 TestFunc來定義。建立基準測試咱們須要使用 BenchmarkFunc來定義。
func TestJoinStrUseNor(t *testing.T) {
    s := JoinStrUseNor("aaa","bbb")
    t.Log(s)
}

func TestJoinStrUseSprint(t *testing.T) {
    s := JoinStrUseSprint("aaa","bbb")
    t.Log(s)
}

func BenchmarkJoinStrUseNor(b *testing.B) {
    b.ResetTimer()
    for i:=0; i<b.N; i++{
        JoinStrUseNor("aaa","bbb")
    }

}

func BenchmarkJoinStrUseSprint(b *testing.B) {
    b.ResetTimer()
    for i:=0; i<b.N; i++{
        JoinStrUseSprint("aaa","bbb")
    }
}
執行基礎測試
go test -bench=. -benchtime=1s -benchmem -count=1
goos: linux
goarch: amd64
pkg: test
BenchmarkJoinStrUseNor-8        79888155                15.5 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrUseSprint-8      8956500               135 ns/op              40 B/op          3 allocs/op
PASS
ok      test    2.930s
命令參數
  • -bench=. 表示指定執行測試函數。.表示執行全部,若是修改成go test -bench=BenchmarkJoinStrUseSprint那麼只會執行BenchmarkJoinStrUseSprint
  • -benchtime=1s指定執行時間爲1s
  • -benchmem顯示內存狀況
  • -count=1表示執行一次
響應參數
  • goos: linux 操做系統
  • goarch: amd64 系統體系架構
  • BenchmarkJoinStrUseNor-8 執行的函數名稱以及對應的GOMAXPROCS值。
  • 79888155 b.N的值
  • 15.5 ns/op 執行一次函數所花費的時間
  • 0 B/op 執行一次函數分配的內存
  • 0 allocs/op 執行一次函數所分配的內存次數
結果分析

經過上面的響應結果參數,咱們很容易得出拼接兩個字符串直接用+號鏈接,比使用fmt.Sprintf()的性能高。golang

樣本分析

有時候由於一些因素的影響,咱們單次測試的結果可能不許備,這個時候咱們就須要進行屢次測試好比go test -bench=BenchmarkJoinStrUseSprint -benchtime=1s -benchmem -count=10將測試的次數定義爲10 或者更大,這個時候我就須要去分析這些結果獲得相對正確的測試結果。可是這個時候時候若是咱們人工去分析,工做量無疑是很大的,並且很困難。這個時候咱們就能夠藉助一個工具 benchstat微信

benchstatGolang官方推薦的一款命令行工具,能夠針對一組或多組樣本進行分析,若是同時分析兩組樣本(好比優化前和優化後),還能夠給出性能變化結果。架構

安裝

go get golang.org/x/perf/cmd/benchstatide

分析
  • 爲了對比咱們增長一個函數
func JoinStrOpt(a,b string) string {
    return  fmt.Sprintf("%s%s",a,b)
}
  • 增長測試
func BenchmarkJoinStrOpt(b *testing.B) {
    b.ResetTimer()
    for i:=0; i<b.N; i++{
        JoinStrOpt("aaa","bbb")
    }
}
  • 執行測試並保存測試結果到before.txt
go test -bench=BenchmarkJoinStrOpt -benchmem -count=10 | tee before.txt
goos: linux
goarch: amd64
pkg: test
BenchmarkJoinStrOpt-8            9143092               131 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9222475               131 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9344643               130 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9127231               131 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9223482               130 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9126334               131 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9364201               129 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9248034               130 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9034518               130 ns/op              40 B/op          3 allocs/op
BenchmarkJoinStrOpt-8            9102846               130 ns/op              40 B/op          3 allocs/op
PASS
ok      test    13.323s
  • 簡單分析結果
benchstat before.txt
name          time/op
JoinStrOpt-8  130ns ± 1%

name          alloc/op
JoinStrOpt-8  40.0B ± 0%

name          allocs/op
JoinStrOpt-8   3.00 ± 0%

能夠看出benchstrat會給我一個執行10測試的結果分析,平均數值以及波動數值。函數

對比分析
  • 修改代碼爲直接相加兩個字符串既JoinStrUseNor的內容
func JoinStrOpt(a,b string) string {
    return  a+b
}
  • 再次執行測試並保存結果到after.txt
>go test -bench=BenchmarkJoinStrOpt -benchmem -count=10 | tee after.txt
goos: linux
goarch: amd64
pkg: test
BenchmarkJoinStrOpt-8           78033046                15.3 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           77211630                15.3 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           78088903                15.4 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           77907912                15.3 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           73805730                15.3 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           78508854                15.3 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           73493384                15.2 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           78618926                15.2 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           74973290                15.2 ns/op             0 B/op          0 allocs/op
BenchmarkJoinStrOpt-8           79287993                15.4 ns/op             0 B/op          0 allocs/op
PASS
ok      test    11.959s
  • 對比分析
>benchstat before.txt after.txt
name          old time/op    new time/op    delta
JoinStrOpt-8     130ns ± 1%      15ns ± 1%   -88.27%  (p=0.000 n=10+10)

name          old alloc/op   new alloc/op   delta
JoinStrOpt-8     40.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)

name          old allocs/op  new allocs/op  delta
JoinStrOpt-8      3.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)

能夠看到benchstat會給我直觀的展現出優化代碼先後的優化差值。工具

對比值括號中的數據含義

p表示結果的可信程度,p 值越大可信程度越低,統計學中一般把p=0.05作爲臨界值,超過此值說明結果不可信,多是樣本過少等緣由。性能

n=10+10表示採用的樣本數,,就跟投票同樣一般會去掉一個最高分,一個最低分。出於某些緣由(好比數據值反常,過大或太小),benchstat會捨棄某些樣本,本例中優化前,優化後的數據沒有捨棄因此是10+10.單元測試

參考資料

期待與您一塊兒交流
白色底可愛幼稚微信公衆號底部二維碼.png測試

相關文章
相關標籤/搜索