如何使用golang bench、benchstat和benchcmp来测量性能

746 阅读1分钟

在golang应用程序中,你可以使用bench 命令来运行基准测试并查看性能结果。你也可以使用benchstatbenchcmp命令来比较过去的结果和新的结果。在下面的例子中,我们将使用两个不同的函数来验证yyy-mm-dd 格式,并为两者编写基准测试。我建议你阅读一篇非常有价值的高性能围棋研讨会的文章。

命令示例

// All benchmarks in the project
go test -v -bench=. -benchmem ./...
go test -v -bench=. ./... -benchmem

// All benchmarks in the package
go test -v -bench=. -benchmem ./internal/validator/

代码

// internal/validator/datetime.go

package validator

import (
	"regexp"
	"time"
)

// DateRegex validates date format `yyyy-mm-dd`.
func DateRegex(v string) bool {
	return regexp.MustCompile(`([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))`).MatchString(v)
}

// TimeParse validates date format `yyyy-mm-dd`.
func TimeParse(v string) bool {
	if _ , e := time.Parse("2006-01-02", v); e != nil {
		return false
	}
	return true
}

单一输入的测试

// internal/validator/datetime_test.go

package validator

import (
	"testing"
)

func BenchmarkDateRegex(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = DateRegex("2020-01-01")
	}
}

func BenchmarkTimeParse(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = TimeParse("2020-01-01")
	}
}

运行

$ go test -v -bench=. -benchmem ./internal/validator/

BenchmarkDateRegex-4   	  133645	      8860 ns/op	    7047 B/op	      62 allocs/op
BenchmarkTimeParse-4   	 7844908	       150 ns/op	       0 B/op	       0 allocs/op

用不同的输入进行测试

// internal/validator/datetime_test.go

package validator

import (
	"testing"
)

func benchmarkDateRegex(v string, b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = DateRegex(v)
	}
}

func BenchmarkDateRegex_1(b *testing.B) { benchmarkDateRegex("", b) }
func BenchmarkDateRegex_2(b *testing.B) { benchmarkDateRegex("     ", b) }
func BenchmarkDateRegex_3(b *testing.B) { benchmarkDateRegex("2020-01-01", b) }

运行

$ go test -v -bench=. -benchmem ./internal/validator/

BenchmarkDateRegex_1-4   	  122085	      8483 ns/op	    7032 B/op	      62 allocs/op
BenchmarkDateRegex_2-4   	  132746	      8445 ns/op	    7032 B/op	      62 allocs/op
BenchmarkDateRegex_3-4   	  132991	      8802 ns/op	    7048 B/op	      62 allocs/op

基准测量

这里我们将过去的结果与当前的结果进行比较。确保你运行go get golang.org/x/perf/cmd/benchstatgo get golang.org/x/tools/cmd/benchcmp 来安装软件包。

$ go test -v -bench=. -benchmem ./internal/validator/ > old.out

// Do some changes to your code

$ go test -v -bench=. -benchmem ./internal/validator/ > new.out

测量

$ benchstat old.out new.out

name         old time/op    new time/op    delta
DateRegex-4    8.98µs ± 0%    8.75µs ± 0%   ~     (p=1.000 n=1+1)
TimeParse-4     151ns ± 0%     152ns ± 0%   ~     (p=1.000 n=1+1)

name         old alloc/op   new alloc/op   delta
DateRegex-4    7.05kB ± 0%    7.05kB ± 0%   ~     (p=1.000 n=1+1)
TimeParse-4     0.00B          0.00B        ~     (all equal)

name         old allocs/op  new allocs/op  delta
DateRegex-4      62.0 ± 0%      62.0 ± 0%   ~     (all equal)
TimeParse-4      0.00           0.00        ~     (all equal)
$ benchcmp old.out new.out

benchmark                old ns/op     new ns/op     delta
BenchmarkDateRegex-4     8978          8752          -2.52%
BenchmarkTimeParse-4     151           152           +0.66%

benchmark                old allocs     new allocs     delta
BenchmarkDateRegex-4     62             62             +0.00%
BenchmarkTimeParse-4     0              0              +0.00%

benchmark                old bytes     new bytes     delta
BenchmarkDateRegex-4     7052          7046          -0.09%
BenchmarkTimeParse-4     0             0             +0.00%