Go 基准测试 Benchmark

个人博客地址

压测Benchmark基准测试 - Jxy 博客

Benchmark基准测试

简单基测

当我们尝试去优化代码的性能时,首先得知道当前的性能怎么样。

Go 语言标准库内置的 testing 测试框架提供了基准测试(benchmark)的能力,能让我们很容易地对某一段代码进行性能测试。

性能测试受环境的影响很大,为了保证测试的可重复性,在进行性能测试时,尽可能地保持测试环境的稳定。

  • 机器处于闲置状态,测试时不要执行其他任务,也不要和其他人共享硬件资源。
  • 机器是否关闭了节能模式,一般笔记本会默认打开这个模式,测试时关闭。
  • 避免使用虚拟机和云主机进行测试,一般情况下,为了尽可能地提高资源的利用率,虚拟机和云主机 CPU 和内存一般会超分配,超分机器的性能表现会非常地不稳定。

参考:https://geektutu.com/post/hpg-benchmark.html

Benchmark是如何工作的

单元测试:

  • 运行当前package内的所有用例:go test 【包名】或 go test .
  • 递归执行当前目录下所有用例:go test ./… 或 go test 【目录名】/…
  • 运行指定文件单元测试: go test -v [单元测试文件]. // 如 go test -v foo_test.go
  • 运行指定单元测试用例:go test -v [单元测试文件] -run [单元测试函数]. //如 go test -v foo_test.go -run TestFoo
  • 压测:go test -bench .
执行参数简介备注
-bench=‘Fib$’可传入正则,匹配用例如只运行以 Fib 结尾的 benchmark 用例
-cpu=2,4可改变 CPU 核数GOMAXPROCS,CPU核数,默认机器的核数
-benchtime=5s
-benchtime=50x
可指定执行时间或具体次数benchmark 的默认时间是 1s,决定了b.N的次数,测试时间
-benchtime的值除了是时间外,还可以是具体的次数。
例如,执行 30 次可以用-benchtime=30x
-count=3可设置 benchmark 轮数参数可以用来设置 benchmark 的轮数,默认是1轮
-benchmem可查看内存分配量和分配次数参数可以度量内存分配的次数,添加此参数后会在结果之后显示 n allocs/op
也就是内存分配了n次,m B/op,
总共分配了 m 字节8003641 B/op == 8 003 641 B=7.63M
-cpuprofile=./cpu.prof生成CPU性能分析执行 CPU profiling,并把结果保存在 cpu.prof
-memprofile=./mem.prof生成内存性能分析执行 Mem profiling,并把结果保存在 cpu.prof 文件中
import (
	"math/rand"
	"testing"
	"time"
)

func generateWithCap(n int) []int {
	rand.Seed(time.Now().UnixNano())
	nums := make([]int, 0, n)
	for i := 0; i < n; i++ {
		nums = append(nums, rand.Int())
	}
	return nums
}

func generate(n int) []int {
	rand.Seed(time.Now().UnixNano())
	nums := make([]int, 0)
	for i := 0; i < n; i++ {
		nums = append(nums, rand.Int())
	}
	return nums
}

func BenchmarkGenerateWithCap(b *testing.B) {
	for n := 0; n < b.N; n++ {
		generateWithCap(1000000)
	}
}

func BenchmarkGenerate(b *testing.B) {
	for n := 0; n < b.N; n++ {
		generate(1000000)
	}
}

$ go test -bench='Generate' -benchmem  -cpu=2,4,8  .    // 执行的指令

goos: darwin   // 操作系统
goarch: arm64  // cpu处理器
pkg: itxj.com/xj-utils/utils/algorithm   // 测试执行所在的包
BenchmarkGenerateWithCap-2            82          13937680 ns/op         8003584 B/op          	1 allocs/op
BenchmarkGenerateWithCap-4            84          14083593 ns/op         8003595 B/op          	1 allocs/op
BenchmarkGenerateWithCap-8            85          13938689 ns/op         8003616 B/op          	1 allocs/op
BenchmarkGenerate-2                   68          15586489 ns/op        45188365 B/op         	40 allocs/op
BenchmarkGenerate-4                   70          15646168 ns/op        45188417 B/op         	40 allocs/op
BenchmarkGenerate-8                   73          15948826 ns/op        45188464 B/op         	41 allocs/op
// 执行测试函数所用CPU核数               执行次数   每次花费时间左移动9位为秒s 每次分配内存字节B左移6位为m  每次分配内存次数
// 如用2核CPU执行BenchmarkGenerate函数               0014083593ns=0.014s    8003584B=7.9m          

PASS
ok      itxj.com/xj-utils/utils/algorithm       7.682s    // 总共执行耗时
结果参数简介
b.Nbenchmark的次数b.N,默认是-benchtime=1s内执行的次数,
b.N 从 -benchtime=1s开始,如果该用例能够在 1s 内完成,
b.N 的值大概以 1, 2, 3, 5, 10, 20, 30, 50, 100 这样的序列递增,越到后面,增加得越快
goos操作系统
goarchcpu处理器
pkg所在的包
BenchmarkGenerate-2
BenchmarkGenerate-4
BenchmarkGenerate-8
【测试函数名】-【cpu核数】BenchmarkGenerate-2,
表示使用2核CPU执行BenchmarkGenerate测试函数
ns/op每次耗时多少毫秒
B/op每次分配内存多少字节Bytes
allocs/op每次分配多少次内存

运行测试用例:

func fib(n int) int {
	if n == 0 || n == 1 {
		return n
	}
	return fib(n-2) + fib(n-1)
}
import "testing"

func BenchmarkFib(b *testing.B) {
	for n := 0; n < b.N; n++ {
		fib(30) // run fib(30) b.N times
	}
}

提高准确度

内存分配情况

不同输入复杂度测试

其他注意事项

  • ResetTimer
  • StopTimer
  • StartTimer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五岁小孩吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值