龙空技术网

Go语言基准测试(benchmark)三部曲之一:基础篇

程序员欣宸 47

前言:

现在我们对“性能测试中的基准测试”大约比较关注,各位老铁们都需要知道一些“性能测试中的基准测试”的相关文章。那么小编也在网络上网罗了一些对于“性能测试中的基准测试””的相关文章,希望你们能喜欢,姐妹们一起来了解一下吧!

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):

Go语言基准测试(benchmark)三部曲完整链接基础篇内存篇提高篇关于基准测试(benchmark)Go的标准库内置的testing框架提供了基准测试(benchmark)功能,可以用来验证本地方法在串行或者并行执行时的基准表现,帮助开发者了解代码的真实性能情况,例如一个方法执行一次的平均耗时,还能看到内存分配的情况关于Go语言基准测试(benchmark)三部曲《Go语言基准测试(benchmark)三部曲》是欣宸的又一系列原创,旨在通过简单的编码实战与大家一同学习和巩固基准测试的常见操作,共分为:基础篇、内存篇、提高篇三部分,每篇都目标明确,用少量代码和命令快速熟悉对应知识点,相信《三部曲》结束后,您也能轻松完成基准测试,根高效的检查代码性能本篇概览作为系列的开篇,本文的目标是和大家一起快速开始基准测试,然后将常用的参数和命令都用上一遍,具体步骤如下编码,写个本地方法,后面就用benchmark来验证这些方法的性能最基本的基准测试匹配规则-cpu参数-benchtime参数-count参数并行测试环境信息操作系统:Windows 11 家庭中文版(22H2),12代i5处理器,16G内存Go:1.19.3VSCode:1.75.1编码benchmark是用来对已有方法做测试的,因此一开始要把被测试的方法准备好,然后像单元测试那样编写benchmark测试代码,最后用go test做基准测试,咱们这就动手把方法准备好准备一个目录,名为benchmark-demo,在目录下执行以下命令,新建一个module

go mod init benchmark-demo
用vscode打开此目录,会识别到module,接下来可以在vscode中操作了新建文件benchmark-demo,里面是用来做基准测试的方法,先写一个简单的方法fib
package main// 斐波拉契数列func fib(n int) int {	if n == 0 || n == 1 {		return n	}	return fib(n-2) + fib(n-1)}
接下来就用benchmark来测试fib方法,看看其性能情况最基本的基准测试最基本的基准测试是从两个维度去检测方法的性能指定时间内,检查方法的运行的耗时指定次数,检查方法的运行的耗时具体操作分为两部写benchmark测试方法,就像写单元测试代码一样,代码位于_test.go结尾的文件中执行benchmark测试先来写benchmakr测试方法,新建名为main_test.go,里面有个方法BenchmarkFib,注意要以Benchmark开始,入参是*testing.B类型,这就是最简单的benchmark方法了
func BenchmarkFib(b *testing.B) {	for n := 0; n < b.N; n++ {		fib(30)	}}
现在用命令行进行测试,执行下面这个最精简的命令,注意:要执行benchmark测试就要带-bench
go test -bench .
很快就完成了基准测试,控制台输出如下,具体含义稍后解释
goos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-16              322           3653937 ns/opPASSok      benchmark-demo  1.999s
最前面几行是基本信息, 整理如下

名称

含义

goos

操作系统,这里是windows

goarch

CPU架构,这里是64位X86

pkg

package名,可以在测试的时候指定package

cpu

CPU的信息,这里可以看到是12代酷睿i5

接下来是benchmark的结果,每个数字的具体解释如下图所示

benchmark也可以像普通单元测试那样添加验证逻辑的代码,测试结果可以是通过和不通过,BenchmarkFib中没有像普通单元测试那样的失败逻辑,因此最终的判断是测试通过,控制台中输出了PASS将同样的测试在M1 Pro芯片的Mac Book Pro上运行一遍试试,获取结果如下,可见和前面的windows测试结果大致相近,不同的是结果中没有CPU信息

go test -bench .goos: darwingoarch: arm64pkg: benchmark-demoBenchmarkFib-8   	     326	   3647077 ns/opPASSok  	benchmark-demo	1.654s
以上就是最基础的benchmark测试了,咱们已经验证了,接下来试试那些常用的参数匹配规则在有多个Benchmark测试方法的时候,如何做到只运行指定的方法呢?先看指定package的指定package:go test -bench benchmark-demo指定子package:go test -bench benchmark-demo/XXX当前目录下的所有package:go test -bench ./… (斜杠左侧是一个点,右侧是三个点)再看指定方法的,可以用正则表达式来指定方法名所有以Fib结尾的方法:go test -bench=‘Fib$’ benchmark-demo所有以BenchmarkNew开始的方法:go test -bench=‘^BenchmarkNew’ benchmark-demo接下来看几个常用参数-cpu参数前面的测试结果BenchmarkFib-16可以看出测试中的GOMAXPROCS等于16,这个值可以用-cpu参数来调整,不过咱们这里不涉及并发编程,GOMAXPROCS的变化对测试结果没有影响,改一下试试,果然没啥波动(稍后还会讲到并行测试,那时候cpu参数的作用就非常明显了)
go test -bench='Fib$' -cpu=2 .  goos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-2               320           3692123 ns/opPASSok      benchmark-demo  1.962s
-benchtime参数前面的命令中我们并没有指定测试时长,因此使用的是默认值1秒,现在咱们来修改这个参数试试,毕竟1秒内完成基准测试并不是普遍适用的指定基准测试时长为10秒:go test -bench=‘Fib$’ -benchtime=10s benchmark-demo结果如下
goos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-16             3264           3668947 ns/opPASSok      benchmark-demo  12.710s
除了指定时间,还能指定次数,就是指定下图黄色箭头所指的值,也就是控制了被测试方法所执行的次数

指定每轮基准测试内的循环次数为999次:go test -bench=‘Fib$’ -benchtime=999x benchmark-demo注意将-benchtime的值从10s改为999x,测试范围就从时间变成了次数,测试结果如下,可见准确的执行了999次

go test -bench='Fib$' -benchtime=999x benchmark-demogoos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-16              999           3667776 ns/opPASSok      benchmark-demo  4.006s
-count参数count参数也是用来控制执行次数的,和前面提到的benchtime不同,count用来控制BenchmarkXXX方法的调用次数,而benchtime是用来控制BenchmarkXXX方法的入参b.N的值,如下图所示

指定每轮基准测试内的循环次数为999次,一共两轮:go test -bench=‘Fib$’ -benchtime=999x -count=2 benchmark-demo,输出如下,还是很容易理解的

go test -bench='Fib$' -benchtime=999x -count=2 benchmark-demogoos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-16              999           3656639 ns/opBenchmarkFib-16              999           3645846 ns/opPASSok      benchmark-demo  7.709s
并行测试前面的BenchmarkFib是常规的串行测试,如果被测试的方法在真实环境中存在并发调用,那么在基准测试中也应该通过并行测试来了解其基本性能(例如锁造成的阻塞)为了对fib方法做并行基准测试,需要编写对应的基准测试代码,如下
func BenchmarkParallelFib(b *testing.B) {	b.RunParallel(func(pb *testing.PB) {		for pb.Next() {			fib(30)		}	})}
执行go test -bench=‘^Benchmark’ benchmark-demo,这时BenchmarkFibBenchmarkParallelFib都会执行,测试结果如下,可见相同时间内,执行fib的总次数是随着并发数量而增加
go test -bench='^Benchmark' benchmark-demo       goos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-16                      368           3362756 ns/opBenchmarkParallelFib-16             3134            370352 ns/opPASSok      benchmark-demo  3.189s
通过cpu参数指定GOMAXPROCS数量,执行命令go test -bench=‘^Benchmark’ -cpu=8 benchmark-demo,结果如下,可见串行方法的测试结果没有变化,而并行测试的结果随着GOMAXPROCS的减少有明显下降
go test -bench='^Benchmark' -cpu=8 benchmark-demogoos: windowsgoarch: amd64pkg: benchmark-democpu: 12th Gen Intel(R) Core(TM) i5-1240PBenchmarkFib-8                       356           3352500 ns/opBenchmarkParallelFib-8              1989            582177 ns/opPASSok      benchmark-demo  3.211s
最后注意,除了cpu参数,前面用过的benchtime和count也都适用于并行测试,含义和串行测试的场景一致至此,最基本的基准测试已经完成了,下一篇咱们会进行内存相关的基准测试,观察内存的使用和分配情况,敬请期待欢迎关注头条号:程序员欣宸学习路上,你不孤单,欣宸原创一路相伴...

标签: #性能测试中的基准测试