GO基准测试

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

基准测试用例约定

  • 基准测试以Benchmark为前缀
  • 需要一个*testing.B类型的参数b
  • 基准测试必须要执行b.N次

testing.B的拥有的方法如下:

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()

动手环节

编写基准测试代码

// fib.go package main import "fmt" func fib(n int) int { if n == 0 || n == 1 { return n } return fib(n-2) + fib(n-1) } func main() { fmt.Println(fib(10)) } // fib_test.go package main import "testing" func BenchmarkFib(b *testing.B) { for n := 0; n < b.N; n++ { fib(30) } } // 测试 go test -bench=Fib -run=none go test -bench=Fib -run=none -benchmem go test -benchmem -bench=. -run=none

测试命令

$ go test -bench=Fib goos: windows goarch: amd64 pkg: test BenchmarkFib-8 228 5253644 ns/op PASStest ok test 1.785s // 结果解析 BenchmarkFib-8 表示对Fib函数进行基准测试,数字8表示 GOMAXPROCS 的值 5253644 ns/op 表示每次调用Fib函数耗时5253644ns 228 这是228次调用的平均值

-benchmem 参数展示内存消耗情况

$ go test -bench=Fib -benchmem goos: windows goarch: amd64 pkg: test BenchmarkFib-8 198 6503562 ns/op 0 B/op 0 allocs/op PASStest ok test 1.785s // 结果解析 0 B/op 表示每次操作内存分配了0字节 0 allocs/op 表示每次操作进行了0次内存分配

-cpu 不同核心cpu结果

go test -bench=Fib -cpu=1 -benchmem

-count 连续跑N次

go test -bench=Fib -count=10 -benchmem

-benchtime 指定运行秒数

go test -bench=Fib -benchtime=10s -benchmem

问题:-run=none参数有什么用?

go test -bench=Fib -run=none // 结果?

测试函数传参-性能测试

很多性能问题是发生在两个不同操作之间的相对耗时,比如同一个函数处理1000个元素的耗时与处理10000甚至100000个元素的耗时的差别是多少?

再或者对于同一个任务究竟使用哪种算法性能最佳?

我们通常需要对两个不同算法的实现使用相同的输入来进行基准比较测试

package main import ( "testing" ) func Add(n int) int { tmp := 0 for i := 0; i <= n; i++ { tmp = tmp + i } return tmp } func benchmarkAdd(i int, b *testing.B) { for n := 0; n < b.N; n++ { // b.N你觉得是什么 Add(i) } } func BenchmarkAdd1000(b *testing.B) { benchmarkAdd(1000, b) } func BenchmarkAdd10000(b *testing.B) { benchmarkAdd(10000, b) } func BenchmarkAdd100000(b *testing.B) { benchmarkAdd(100000, b) }

bench测试

$ go test -bench=. goos: linux goarch: amd64 pkg: test cpu: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz BenchmarkGenerate1000-8 3997779 303.6 ns/op BenchmarkGenerate10000-8 402241 2889 ns/op BenchmarkGenerate100000-8 42884 28545 ns/op PASS ok test 4.225s // 默认情况下,每个基准测试至少运行1秒。如果在Benchmark函数返回时没有到1秒,则b.N的值会按1,2,5,10,20,50,…增加,并且函数再次运行。

-benchtime标志增加最小基准时间,以产生更准确的结果

$ go test -bench=. -benchtime=20s goos: linux goarch: amd64 pkg: test cpu: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz BenchmarkAdd1000-8 81030480 293.2 ns/op BenchmarkAdd10000-8 8304865 2848 ns/op BenchmarkAdd100000-8 846728 28599 ns/op PASS ok test 75.148s

b.ResetTimer-重置时间:一般加在不计划作为测试报告的操作之后

func benchmarkAdd(i int, b *testing.B) { time.Sleep(1 * time.Second) b.ResetTimer() // -----------------例子------------------- for n := 0; n < b.N; n++ { Add(i) } }

b.SetParallelism()-设置使用CPU数 // 加了实际没生效 go1.16版本 linux环境 建议使用命令行参数 -cpu=n

func benchmarkAdd(i int, b *testing.B) { b.SetParallelism(2) // -----------------例子------------------- for n := 0; n < b.N; n++ { Add(i) } }

b.RunParallel()-并行测试:创建出多个goroutine,goroutine数量默认为 GOMAXPROCS 数量也就是CPU核数

// 例子 func benchmarkAdd(i int, b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { Add(i) } }) } // SetParallelism() 加了实际没生效 go1.16版本 linux环境 func benchmarkAdd(i int, b *testing.B) { b.SetParallelism(1) b.RunParallel(func(pb *testing.PB) { for pb.Next() { Add(i) } }) } // -cpu go test -bench=. -cpu=1 go test -bench=. -cpu=2 go test -bench=. -cpu=4 go test -bench=. -cpu=8

__EOF__

本文作者每天记录一点点,日积月累 - rxg456
本文链接https://www.cnblogs.com/rxg456/p/16221889.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   rxg456  阅读(158)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示