官术网_书友最值得收藏!

46.1 性能基準測試在Go語言中是“一等公民”

在前文中,我們已經接觸過許多性能基準測試。和上一條所講的模糊測試的境遇不同,性能基準測試在Go語言中是和普通的單元測試一樣被原生支持的,得到的是“一等公民”的待遇。我們可以像對普通單元測試那樣在*_test.go文件中創建被測對象的性能基準測試,每個以Benchmark前綴開頭的函數都會被當作一個獨立的性能基準測試:

func BenchmarkXxx(b *testing.B) {
    //...
}

下面是一個對多種字符串連接方法的性能基準測試(改編自第15條):

// chapter8/sources/benchmark_intro_test.go

var sl = []string{
    "Rob Pike ",
    "Robert Griesemer ",
    "Ken Thompson ",
}

func concatStringByOperator(sl []string) string {
    var s string
    for _, v := range sl {
        s += v
    }
    return s
}

func concatStringBySprintf(sl []string) string {
    var s string
    for _, v := range sl {
        s = fmt.Sprintf("%s%s", s, v)
    }
    return s
}

func concatStringByJoin(sl []string) string {
    return strings.Join(sl, "")
}

func BenchmarkConcatStringByOperator(b *testing.B) {
    for n := 0; n < b.N; n++ {
        concatStringByOperator(sl)
    }
}

func BenchmarkConcatStringBySprintf(b *testing.B) {
    for n := 0; n < b.N; n++ {
        concatStringBySprintf(sl)
    }
}

func BenchmarkConcatStringByJoin(b *testing.B) {
    for n := 0; n < b.N; n++ {
        concatStringByJoin(sl)
    }
}

上面的源文件中定義了三個性能基準測試:BenchmarkConcatStringByOperator、Benchmark-ConcatStringBySprintf和BenchmarkConcatStringByJoin。我們可以一起運行這三個基準測試:

$go test -bench . benchmark_intro_test.go
goos: darwin
goarch: amd64
BenchmarkConcatStringByOperator-8       12810092            88.5 ns/op
BenchmarkConcatStringBySprintf-8         2777902             432 ns/op
BenchmarkConcatStringByJoin-8           23994218            49.7 ns/op
PASS
ok         command-line-arguments 4.117s

也可以通過正則匹配選擇其中一個或幾個運行:

$go test -bench=ByJoin ./benchmark_intro_test.go
goos: darwin
goarch: amd64
BenchmarkConcatStringByJoin-8     23429586            49.1 ns/op
PASS
ok         command-line-arguments 1.209s

我們關注的是go test輸出結果中第三列的那個值。以BenchmarkConcatStringByJoin為例,其第三列的值為49.1 ns/op,該值表示BenchmarkConcatStringByJoin這個基準測試中for循環的每次循環平均執行時間為49.1 ns(op代表每次循環操作)。這里for循環調用的是concatStringByJoin,即執行一次concatStringByJoin的平均時長為49.1 ns。

性能基準測試還可以通過傳入-benchmem命令行參數輸出內存分配信息(與基準測試代碼中顯式調用b.ReportAllocs的效果是等價的):

$go test -bench=Join ./benchmark_intro_test.go -benchmem
goos: darwin
goarch: amd64
BenchmarkConcatStringByJoin-8     23004709   48.8 ns/op   48 B/op     1 allocs/op
PASS
ok         command-line-arguments 1.183s

這里輸出的內存分配信息告訴我們,每執行一次concatStringByJoin平均進行一次內存分配,每次平均分配48字節的數據。

主站蜘蛛池模板: 两当县| 高雄市| 灵宝市| 莱西市| 池州市| 扶绥县| 五原县| 临朐县| 卢氏县| 昭觉县| 南木林县| 嵊州市| 辉南县| 铅山县| 玉田县| 灵石县| 任丘市| 阿克| 辛集市| 焉耆| 雷波县| 仙桃市| 平潭县| 依兰县| 密云县| 大名县| 凯里市| 吕梁市| 青川县| 铁岭市| 兴仁县| 常熟市| 永胜县| 荣成市| 曲松县| 多伦县| 顺昌县| 南木林县| 科技| 金溪县| 鲁甸县|