go语言学习笔记 — 基础 — go工具(5.2): 基准测试 (性能测试)—— 获得代码内存占用和运行效率的性能数据
Posted Locutus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言学习笔记 — 基础 — go工具(5.2): 基准测试 (性能测试)—— 获得代码内存占用和运行效率的性能数据相关的知识,希望对你有一定的参考价值。
基准测试可以测试一段程序的运行性能和耗费CPU的程度。go提供了基准测试框架,可以打印出非常标准的测试报告。benchmark,意为基准。
1. 基准测试的基本使用
- 测试文件以
_test.go
结尾 - 测试用例函数以func Benchmark_XXX(b *testing.B) 开头
- b.N由基准测试框架提供
package go_test
// 在同一个包文件夹下,go源文件的package声明必须是同一个包名,否则会报错:package benchmark_test
import "testing"
func Benchmark_add(b *testing.B) {
var n int
for i := 0; i<b.N; i++ {
n++
}
}
运行基准测试
# go test -v -bench=. benchmark_test.go
goos: darwin
goarch: amd64
Benchmark_add-4 2000000000 0.51 ns/op
PASS
ok command-line-arguments 1.071s
-bench=.
表示运行测试文件中所有的基准测试用例,相当于单元测试中的-run
;Benchmark_add-4是基准测试名字,2000000000是基准测试次数,是testing.B中提供给程序使用的N;0.51 ns/op
表示每一次操作耗费时间(纳秒)
2. 基准测试原理
基准测试框架对一个测试用例的默认测试时间是1s。当以benchmark开头的基准测试用例函数返回时,用时不到1s,那么testing.B中的N值将按1、2、5、10、20、50的速率递增,同时以递增后的值重新调用基准测试用例函数。
3. 自定义测试时间
使用-benchtime参数自定义基准测试时间。
# go test -v -bench=. -benchtime=5s benchmark_test.go
goos: darwin
goarch: amd64
Benchmark_add-4 10000000000 0.39 ns/op
PASS
ok command-line-arguments 3.942s
4. 测试内存
基准测试可以统计一段代码可能存在的内存分配。
package go_test
import "testing"
func Benchmark_add(b *testing.B) {
var n int
for i := 0; i<b.N; i++ {
n++
}
}
func Benchmark_Alloc(b *testing.B) {
for i := 0; i<b.N;i++ {
fmt.Printf("%d", i)
}
}
只运行Alloc基准测试用例
# go test -v -bench=Alloc -benchmem benchmark_mem_test.go
goos: darwin
goarch: amd64
Benchmark_Alloc-4 20000000 122 ns/op 16 B/op 2 allocs/op
PASS
ok command-line-arguments 2.563s
-bench=Alloc
表示只运行Benchmark_Alloc的测试用例;16 B/op
表示每一次测试用例调用需要16个字节;2 allocs/op
表示每一次调用有两次内存分配。
开发根据这些信息,确定可能的内存分配点,进行优化和调整。
- 命令行选项
选项 | 备注 |
---|---|
-v | 可视化输出测试信息 |
-bench | 指定基准测试用例的名称,若-bench=. 则表示全部测试;若-bench=XXX 则表示测试Benchmark_XXX用例,XXX为函数Benchmark_XXX的实际用例名称 |
-benchmem | 显示内存分配情况 |
-benchtime=5s | 自定义基准测试时间 |
5. 计时器控制
有些测试需要一定的启动和初始化时间,如果从Benchmark_XXX()函数开始计时会很大程度上影响测试结果的准确性。testing.B提供了一系列方法可以方便地了解计时器控制,从而使计时器只在需要的代码区间进行测试。
package go_test
import (
"testing"
)
func Benchmark_Add_TimerController(b *testing.B) {
// 重置计时器
b.ResetTimer()
// 停止计时器
b.StopTimer()
// 开始计时器
b.StartTimer()
var n int
for i := 0; i < b.N; i++ {
n++
}
}
从Benchmark_XXX函数一开始,计数器就开始计数,因此需要b.ResetTimer()重置计时器,然后b.StopTimer()停止计时器,接着b.StartTimer()开始计时器,做耗时操作的计数。
以上是关于go语言学习笔记 — 基础 — go工具(5.2): 基准测试 (性能测试)—— 获得代码内存占用和运行效率的性能数据的主要内容,如果未能解决你的问题,请参考以下文章
go语言学习笔记 — 基础 — go工具:编译 —— go build
go语言学习笔记 — 基础 — go工具:编译并安装 —— go install
go语言学习笔记 — 基础 — go工具:编译后运行 —— go run
go语言学习笔记 — 基础 — go工具:一键获取源代码,编译并安装 —— go get