怎么写Go基准测试 | 青训营笔记

简介: 怎么写Go基准测试 | 青训营笔记

前言

记录加入青训营的每一天笔记。

或许你经常会思考这样的问题,我用不同的方法实现了同样的效果,哪个会更快?哪个内存消耗更小?这时候你一个简单的基准测试就能解决你的疑惑。

Go向来是以工具丰富而著称的,在学习Go的过程中,你会发现无论是写一个单元测试,还是做一些竞争检测都能很快的上手,而且用的很痛快。当然,接下来要说的基准测试也一样。

基准测试工具就在Go的测试包中,下面就用一个例子来介绍。

举个栗子

由于一些场景需要,我需要将[]byte输出16进制字符。

有时候我会这么写:

fmt.Sprintf("%x", b)

但有时候我会这么写:

hex.EncodeToString(b)

但到底哪种写法更好呢?今天我就来比较一下。

直接写了个main.go

func EncodeA(b []byte) string {
    return fmt.Sprintf("%x", b)
}
func EncodeB(b []byte) string {
    return hex.EncodeToString(b)
}

再写个测试main_test.go

var buf = []byte("skdjadialsdgasadasdhsakdjsahlskdjagloqweiqwo")
func BenchmarkEncodeA(b *testing.B) {
    for i := 0; i < b.N; i++ {
        EncodeA(buf)
    }
}
func BenchmarkEncodeB(b *testing.B) {
    for i := 0; i < b.N; i++ {
        EncodeB(buf)
    }
}

就这么简单,我们的基本测试就写完了。从我的写法中你也许就知道:

  • 和单元测试一样,都写在_test.go文件中;
  • 需要以Benchmark为函数名开头;
  • 和单元测试类似,必须接受一个*testing.B参数;
  • 被测试代码放在一个循环中。

我们直接跑一下。当然我们也是用go test来执行测试,简单的测试只要带上-bench=.就可以了。

$ go test -bench=.
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               265 ns/op
BenchmarkEncodeB-8      10000000               161 ns/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        3.397s

前两行是平台信息,第三行包名。第四、五行就是测试的结果了。

  • BenchmarkEncodeA-8 ,BenchmarkEncodeB-8 基准测试函数名-GOMAXPROCS
  • 5000000,10000000 被测试的函数执行次数,也就是EncodeA()被执行了5000000次,EncodeB()被执行了10000000次,也就是b.N的值了。
  • 265 ns/op,161 ns/op表示每次调用被测试函数花费的时间。

从花费的时间上来看,我们知道EncodeB()要快一点。

更多

你以为就这么简单的结束了么?NONONO。

  • -bench 可接收一个有效的正则表达式来执行符合条件的测试函数。当你的函数很多时,可以用它来过滤.
$ go test -bench=BenchmarkEncodeA
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               256 ns/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        1.575s
  • -benchmem可以查看内存分配
$ go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               261 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               162 ns/op             192 B/op          2 allocs/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        3.408s

其中B/op 表示每次执行会分配多少内存,allocs/op表示每次执行会发生多少次内存分配。

  • -benchtime指定每个测试执行的时间。默认1s,当你的函数比较耗时你可以设置更长一点。因为b.N是与这个时间有关的。
    当你的运行时间没达到-benchtime制定的时间前,b.N将以1,2,5,10,20,50…增加,然后重新运行测试代码。
$ go test -bench=. -benchmem -benchtime=5s
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8      30000000               254 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeB-8      50000000               160 ns/op             192 B/op          2 allocs/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        16.113s
  • -count指定每个测试执行的次数。
$ go test -bench=. -benchmem -count=3
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               256 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeA-8       5000000               255 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeA-8       5000000               253 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               163 ns/op             192 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               160 ns/op             192 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               160 ns/op             192 B/op          2 allocs/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        9.984s

我常用的也就这些了。

但对于testing.B来说,它拥有了testing.T的全部接口,所以Fail,Skip,Error这些都可以用,而且还增加了

  • SetBytes( i uint64) 统计内存消耗。
  • SetParallelism(p int) 制定并行数目。
  • StartTimer / StopTimer / ResertTimer 操作计时器。

你可以按需使用。r

注意

b.N为一个自增字段,谨慎用它做函数参数。

目录
相关文章
|
1月前
|
数据库连接 Go 数据库
Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性
本文探讨了Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性;防御编程则强调在编码时考虑各种错误情况,确保程序健壮性。文章详细介绍了这两种技术在Go语言中的实现方法及其重要性,旨在提升软件质量和可靠性。
38 1
|
1月前
|
测试技术 Go
go语言中测试工具
【10月更文挑战第22天】
35 4
|
2月前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
1007 3
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
2月前
|
测试技术
自动化测试项目实战笔记(三):测试用户注册(验证码错误,成功,出现弹框时处理)
本文是关于自动化测试项目实战笔记,主要介绍了如何测试用户注册功能,包括验证码错误、注册成功以及弹框处理的测试步骤和代码实现。
138 2
自动化测试项目实战笔记(三):测试用户注册(验证码错误,成功,出现弹框时处理)
|
2月前
|
Java 关系型数据库 MySQL
自动化测试项目实战笔记(一):JDK、Tomcat、MySQL、Jpress环境安装和搭建
这篇文章是关于自动化测试项目实战笔记,涵盖了JDK、Tomcat、MySQL、Jpress环境的安装和搭建过程,以及测试用例和常见问题总结。
61 1
自动化测试项目实战笔记(一):JDK、Tomcat、MySQL、Jpress环境安装和搭建
|
2月前
|
安全
红队测试方法论-课程笔记
红队测试方法论-课程笔记
红队测试方法论-课程笔记
|
2月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
137 1
|
2月前
|
计算机视觉
目标检测笔记(二):测试YOLOv5各模块的推理速度
这篇文章是关于如何测试YOLOv5中不同模块(如SPP和SPPF)的推理速度,并通过代码示例展示了如何进行性能分析。
139 3
|
2月前
|
人工智能 算法 测试技术
自动化测试项目实战笔记(二):解决验证码识别问题
这篇文章介绍了三种自动化测试中验证码识别的方法:使用Python的pytesseract和PIL模块、利用第三方API如万维易源,以及使用开源的ddddocr库,还提到了一些注意事项,比如如何获取验证码区域的截图。
98 2
|
2月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
80 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)