Go之Benchmark

一、概念

基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器。

指定一个时间(默认是1秒),看测试对象在达到时间上限时,最多能被执行多少次和在此期间测试对象内存分配情况。

 

二、特点

  1. 基准测试的代码文件必须以_test.go结尾
  2. 基准测试的函数必须以Benchmark开头
  3. 基准测试函数必须接受一个指向Benchmark类型的指针作为唯一参数
  4. 基准测试函数不能有返回值
  5. b.ResetTimer是重置计时器,这样可以避免for循环之前的初始化代码的干扰
  6. 最后的for循环很重要,被测试的代码要放到循环里
  7. b.N是基准测试框架提供的,表示循环的次数

 

三、常用API

  1. b.StopTimer()
  2. b.StartTimer()
  3. b.ResetTimer()
  4. b.Run(name string, f func(b *B))
  5. b.RunParallel(body func(*PB))
  6. b.ReportAllocs()
  7. b.SetParallelism(p int)
  8. b.SetBytes(n int64)
  9. testing.Benchmark(f func(b *B)) BenchmarkResult

 

四、操作的命令

go test -bench=BenchmarkFoo

go test -bench=.

// 加上 -bench= 测试名字, .表示运行所有的基准测试,名字可用正则。

go test -bench=BenchmarkFoo -benchtime=5s/10000x

// 加上 -benchtime 设置时间,s表示秒,x表示执行次数

go test -bench=BenchmarkFoo -benchtime=5s -count=3

// 加上 -count 表示几次测试

go test -bench=. -benchmem

// 加上 -benchmem 查看内存

go test -bench=. -benchmem -cpuprofile profile.out

go test -bench=. -benchmem -memprofile memprofile.out

go tool pprof profile.out

go tool pprof memprofile.out

// 结合 pprof 输出查看 cpu和内存。

 

五、使用的方式

串行

func BenchmarkFoo(b *testing.B) {
  for i:=0; i<b.N; i++ {
    dosomething()
  }
}

并行

func BenchmarkFoo(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			dosomething()
		}
	})
}

并行的goroutine个数是默认等于runtime.GOMAXPROCS(0)。

释义:创建P个goroutine之后,再把b.N打散到每个goroutine上执行

增大goroutine的个数,使用 b.SetParallelism(p int)

func BenchmarkFoo(b *testing.B) {
b.SetParallelism(10)
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			dosomething()
		}
	})
}

// 原理: 最终goroutine个数 = 形参p的值 * runtime.GOMAXPROCS(0)

numProcs := b.parallelism * runtime.GOMAXPROCS(0)

 

StartTimer()、StopTimer()、ResetTimer()

init(); // 初始化工作
b.ResetTimer()
for i:=0; i<b.N; i++ { dosomething1() }
b.StopTimer()

otherWork(); // 例如做一些转换工作
b.StartTimer()
for i:=0; i<b.N; i++ { dosomething2() }

方式二

init(); // 初始化工作
b.ResetTimer()
for i:=0; i<b.N; i++ {
  flag := dosomething()
  if flag {
    b.StopTimer()
  } else {
    b.StartTimer()
  }
}

StartTimer()、ResetTimer() 都是记录当前时间为开始时间 和 内存分配情况,不过 ResetTimer()多了清空重置操作。

StopTimer() 累计记录执行的时间(当前时间 - 记录的开始时间),累计记录内存分配次数和分配字节数

Run()

表驱动法

func BenchmarkRR(b *testing.B) {
	tests := []struct {
		keyLength   int
	}{
		{keyLength: 16},
		{keyLength: 32},
	}
	for _, t := range tests {
		name := fmt.Sprintf("%vKeyLength", t.keyLength)
		b.Run(name, func(b *testing.B) {
			dosomething(b, t.keyLength)
		})
	}
}

 

六、例子

fib.go

// 斐波那契数列
func fib(n int) int {
	if n < 2 {
		return n
	}
	return fib(n-1) + fib(n-2)
}
func sum(a, b int) int {
	return a + b
}

 

fib_test.go

import "testing"
func BenchmarkFib10(b *testing.B) {
	for n := 0; n < b.N; n++ {
		fib(10)
	}
}
func BenchmarkFib20(b *testing.B) {
	for n := 0; n < b.N; n++ {
		fib(20)
	}
}
func BenchmarkSum(b *testing.B) {
	for n := 0; n < b.N; n++ {
		sum(1, 2)
	}
}

 

使用正则

使用-benchting

使用-benchting 的x单位

使用-count

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值