Skip to content

基准测试

函数格式

基准测试就是在一定的工作负载之下检测程序性能的一种方法。基准测试的基本格式如下:

plain
func BenchmarkName(b *testing.B){
    // ...
}

基准测试以Benchmark为前缀,需要一个*testing.B类型的参数 b,基准测试必须要执行b.N次,这样的测试才有对照性,b.N的值是系统根据实际情况去调整的,从而保证测试的稳定性。 testing.B拥有的方法如下:

plain
func (c *B) Error(args ...interface{})
func (c *B) Errorf(format string, args ...interface{})
func (c *B) Fail()
func (c *B) FailNow()
func (c *B) Failed() bool
func (c *B) Fatal(args ...interface{})
func (c *B) Fatalf(format string, args ...interface{})
func (c *B) Log(args ...interface{})
func (c *B) Logf(format string, args ...interface{})
func (c *B) Name() string
func (b *B) ReportAllocs()
func (b *B) ResetTimer()
func (b *B) Run(name string, f func(b *B)) bool
func (b *B) RunParallel(body func(*PB))
func (b *B) SetBytes(n int64)
func (b *B) SetParallelism(p int)
func (c *B) Skip(args ...interface{})
func (c *B) SkipNow()
func (c *B) Skipf(format string, args ...interface{})
func (c *B) Skipped() bool
func (b *B) StartTimer()
func (b *B) StopTimer()

测试示例

go
func BenchmarkSplit(b *testing.B) {
	for i := 0; i < b.N; i++ {
		SplitStr("a:b:c:d", ":")
	}
}

然后运行测试用例:

使用代码go test -bench=Split

go
PS E:\DEV\Go\src\code.rookieops.com\day05\splitStr> go test -bench=Split
goos: windows
goarch: amd64
pkg: code.rookieops.com/day05/splitStr
BenchmarkSplit-4         2999503               409 ns/op
PASS
ok      code.rookieops.com/day05/splitStr       3.633s
`BenchmarkSplit-4``4``GOMAXPROCS``2999503``ns/op``Split``409ns``2999503``-benchmem`
go
go test -bench=Split -benchmem
goos: windows
goarch: amd64
pkg: code.rookieops.com/day05/splitStr
BenchmarkSplit-4         3591652               311 ns/op             112 B/op          3 allocs/op
PASS
ok      code.rookieops.com/day05/splitStr       2.219s
`112 B/op``3 allocs/op``Split`
go
package splitStr

import "strings"

// SplitStr ..
func SplitStr(s, sep string) (res []string) {
	// 取索引
	res = make([]string, 0, strings.Count(s, sep)+1)
	index := strings.Index(s, sep)
	for index >= 0 {
		res = append(res, s[:index])
		s = s[index+len(sep):]
		index = strings.Index(s, sep)
	}
	res = append(res, s)
	return
}

然后运行测试代码如下:

go
 go test -bench=Split -benchmem
goos: windows
goarch: amd64
pkg: code.rookieops.com/day05/splitStr
BenchmarkSplit-4         4508462               233 ns/op              64 B/op          1 allocs/op
PASS
ok      code.rookieops.com/day05/splitStr       3.234s

性能比较函数

性能比较函数是对一个函数处理不同请求的差别。

如下编写一个斐波拉契函数:

go
// Fib 斐波拉契函数
func Fib(n int) int {
	if n < 2 {
		return n
	}
	return Fib(n-1) + Fib(n-2)
}

然后我们编写性能比较函数:

go
func benchmarkFib(b *testing.B, n int) {
	for i := 0; i < b.N; i++ {
		Fib(n)
	}
}

func BenchmarkFib1(b *testing.B) {
	benchmarkFib(b, 1)
}

func BenchmarkFib2(b *testing.B) {
	benchmarkFib(b, 2)
}

func BenchmarkFib3(b *testing.B) {
	benchmarkFib(b, 3)
}

运行测试用例代码如下:

go
PS E:\DEV\Go\src\code.rookieops.com\day05\splitStr> go test -bench=Fib1
goos: windows
goarch: amd64
pkg: code.rookieops.com/day05/splitStr
BenchmarkFib1-4         278520369                4.16 ns/op
PASS
ok      code.rookieops.com/day05/splitStr       2.819s
PS E:\DEV\Go\src\code.rookieops.com\day05\splitStr> go test -bench=Fib2
goos: windows
goarch: amd64
pkg: code.rookieops.com/day05/splitStr
BenchmarkFib2-4         128817837                8.50 ns/op
PASS
ok      code.rookieops.com/day05/splitStr       2.764s
PS E:\DEV\Go\src\code.rookieops.com\day05\splitStr> go test -bench=Fib3
goos: windows
goarch: amd64
pkg: code.rookieops.com/day05/splitStr
BenchmarkFib3-4         80003732                16.0 ns/op
PASS
ok      code.rookieops.com/day05/splitStr       2.283s
最近更新