Golang基准测试
仙人技术
共 15152字,需浏览 31分钟
· 2021-08-23
目录
1、基本使用
2、bench 的工作原理
3、传入 cpu num 进行测试
4、count 多次运行基准测试
5、benchtime 指定运行秒数
6、ResetTimer 重置定时器
7、benchmem 展示内存消耗
1、基本使用
基准测试常用于代码性能测试,函数需要导入testing
包,并定义以Benchmark
开头的函数, 参数为testing.B
指针类型,在测试函数中循环调用函数多次
go test testcalc/calc -bench .
go test testcalc/calc -bench . -run=none
# 显示内存信息
go test testcalc/calc -bench . -benchmem
go test -bench=. -benchmem -run=none
go test
会在运行基准测试之前之前执行包里所有的单元测试,所有如果你的包里有很多单元测试,或者它们会运行很长时间,你也可以通过go test
的-run
标识排除这些单元测试
业务代码fib.go
,测试斐波那契数列
package pkg06
func fib(n int) int {
if n == 0 || n == 1 {
return n
}
return fib(n-2) + fib(n-1)
}
测试代码fib_test.go
package pkg06
import "testing"
func BenchmarkFib(b *testing.B) {
for n := 0; n < b.N; n++ {
fib(30)
}
}
执行测试
➜ go test -bench=. -run=none
goos: darwin
goarch: amd64
pkg: pkg06
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkFib-12 250 4682682 ns/op
PASS
ok pkg06 1.875s
➜ go test -bench=. -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg06
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkFib-12 249 4686452 ns/op 0 B/op 0 allocs/op
PASS
ok pkg06 1.854s
2、bench 的工作原理
基准测试函数会被一直调用直到 b.N
无效,它是基准测试循环的次数b.N
从1
开始,如果基准测试函数在1
秒内就完成 (默认值),则b.N
增加,并再次运行基准测试函数b.N
的值会按照序列1,2,5,10,20,50,...
增加,同时再次运行基准测测试函数上述结果解读代表 1
秒内运行了250
次,每次4682682 ns
-12
后缀和用于运行次测试的GOMAXPROCS
值有关。与GOMAXPROCS
一样,此数字默认为启动时Go
进程可见的CPU
数。可以使用-cpu
标识更改此值,可以传入多个值以列表形式来运行基准测试
3、传入 cpu num 进行测试
➜ go test -bench=. -cpu=1,2,4 -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg06
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkFib 244 4694667 ns/op 0 B/op 0 allocs/op
BenchmarkFib-2 255 4721201 ns/op 0 B/op 0 allocs/op
BenchmarkFib-4 256 4756392 ns/op 0 B/op 0 allocs/op
PASS
ok pkg06 5.826s
4、count 多次运行基准测试
因为热缩放、内存局部性、后台处理、gc
活动等等会导致单次的误差,所以一般会进行多次测试
➜ go test -bench=. -count=10 -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg06
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkFib-12 217 5993577 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 246 5065577 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 244 4955397 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 255 4689529 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 254 4879802 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 254 4691213 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 255 4772108 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 240 4724141 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 255 4717087 ns/op 0 B/op 0 allocs/op
BenchmarkFib-12 255 4787803 ns/op 0 B/op 0 allocs/op
PASS
ok pkg06 18.166s
5、benchtime 指定运行秒数
有的函数比较慢,为了更精确的结果,可以通过-benchtime
标志指定运行时间,从而使它运行更多次
➜ go test -bench=. -benchtime=5s -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg06
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkFib-12 1128 4716535 ns/op 0 B/op 0 allocs/op
PASS
ok pkg06 7.199s
6、ResetTimer 重置定时器
可能在真正测试之前还需要做很多例如初始化等工作,这时可以在需要测试的函数执行之初添加一个重置定时器的功能,这样最终得到的时间就更为精确
package pkg06
import (
"testing"
"time"
)
func BenchmarkFib(b *testing.B) {
time.Sleep(3 * time.Second)
b.ResetTimer()
for n := 0; n < b.N; n++ {
fib(30)
}
}
执行测试
➜ go test -bench=. -benchtime=5s -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg06
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkFib-12 1239 4712413 ns/op 0 B/op 0 allocs/op
PASS
ok pkg06 16.122s
7、benchmem 展示内存消耗
例如测试大 cap
的切片,直接用cap
初始化和cap
动态扩容进行对比
package pkg07
import (
"math/rand"
"testing"
"time"
)
// 指定大的cap的切片
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
}
// 动态扩容的slice
func generateDynamic(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(100000)
}
}
func BenchmarkGenerateDynamic(b *testing.B) {
for n := 0; n < b.N; n++ {
generateDynamic(100000)
}
}
执行测试
➜ go test -bench=. -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg07
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkGenerateWithCap-12 672 1729465 ns/op 802817 B/op 1 allocs/op
BenchmarkGenerateDynamic-12 561 2122992 ns/op 4654346 B/op 30 allocs/op
PASS
ok pkg07 3.777s
结论:用cap
初始化好的性能可以高一个数据量级
例如测试测试函数复杂度,不带 cap
的slice
动态扩容
对上面代码中调用动态扩容生成切片进行再次封装
package pkg08
import (
"math/rand"
"testing"
"time"
)
// 指定大的cap的切片
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
}
// 动态扩容的slice
func generateDynamic(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 benchmarkGenerate(i int, b *testing.B) {
for n := 0; n < b.N; n++ {
generateDynamic(i)
}
}
func BenchmarkGenerateDynamic1000(b *testing.B) { benchmarkGenerate(1000, b) }
func BenchmarkGenerateDynamic10000(b *testing.B) { benchmarkGenerate(10000, b) }
func BenchmarkGenerateDynamic100000(b *testing.B) { benchmarkGenerate(100000, b) }
func BenchmarkGenerateDynamic1000000(b *testing.B) { benchmarkGenerate(1000000, b) }
func BenchmarkGenerateDynamic10000000(b *testing.B) { benchmarkGenerate(10000000, b) }
执行测试
➜ go test -bench=. -benchmem -run=none
goos: darwin
goarch: amd64
pkg: pkg08
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkGenerateDynamic1000-12 39540 26557 ns/op 16376 B/op 11 allocs/op
BenchmarkGenerateDynamic10000-12 5452 210894 ns/op 386296 B/op 20 allocs/op
BenchmarkGenerateDynamic100000-12 572 2106325 ns/op 4654341 B/op 30 allocs/op
BenchmarkGenerateDynamic1000000-12 48 23070939 ns/op 45188416 B/op 40 allocs/op
BenchmarkGenerateDynamic10000000-12 5 212567041 ns/op 423503110 B/op 50 allocs/op
PASS
ok pkg08 9.686s
结论:输入变为原来的10
倍,单次耗时也差不多是上一级的10
倍。说明这个函数的复杂度是接近线性的
See you ~
评论
测试新人,如何快速上手一个陌生的系统!
大家好,我是狂师!作为刚入行不久的测试新人,面对一个陌生的系统时,可能会感到有些手足无措。面对一个全新的系统系统,如何快速上手并展开有效的测试工作是一个重要的挑战。本文将探讨测试新人如何通过一系列步骤和策略,快速熟悉并掌握新系统的测试要点,从而提高测试效率和质量。本文旨在为测试新手提供一份指导,帮助
测试开发技术
0
APP 安全测试项总结
一、安装包测试 1.1、关于反编译 目的是为了保护公司的知识产权和安全方面的考虑等,一些程序开发人员会在源码中硬编码一些敏感信息,如密码。而且若程序内部一些设计欠佳的逻辑,也可能隐含漏洞,一旦源码泄漏,安全隐患巨大。 为了避免这些问题,除了代码审核外,通常开发的做法是对代码进行混淆,混淆后源代
测试开发技术
0
自动化测试做得好的标准是什么
自动化测试要做得好的标准,主要包括以下几个方面:一、高覆盖率与精准定位1、测试用例覆盖全面:自动化测试应覆盖产品的核心功能、关键业务流程以及常见的异常场景,确保测试范围广泛,降低遗漏风险。2、问题定位准确:自动化测试应能够精准地识别并定位问题,包括缺陷的位置、产生的原因以及可能的影响,为开发团队提供
测试开发社区
0
21.3K star!推荐一款可视化自动化测试/爬虫/数据采集神器!功能免费且强大!
【温馨提示】由于公众号更改了推送规则,不再按照时间顺序排列,如果不想错过测试开发技术精心准备的的干货文章,请将测试开发技术设为“星标☆”,看完文章在文尾处点亮“在看”!大家好,我是狂师!在大数据时代,信息的获取与分析变得尤为重要。对于开发者、数据分析师乃至非技术人员来说,能够高效地采集网络数据并进行
测试开发技术
4
使用 GitHub Actions 构建 Golang PGO
今年 2 月,我宣布 Dolt 版本现已构建为配置文件引导优化 (pgo) 二进制文件,利用 Golang 1.20 的强大功能将 Dolt 的读取性能提高 5.3%。在我宣布这一消息之前,我们的一位常驻 Golang 专家 Zach 试验并测试了 Golang 的 pgo 功能
GoCN
0
8年软件测试工程师感悟——写给还在迷茫中的朋友
这两天和朋友谈到行业的发展,为什么互联网大厂纷纷大规模裁员?以前在全网声讨互联网企业996呢,今年突然没声音了,也不用讨论在哪个路灯上吊死互联网资本家了,因为都被裁了。继芯片领域大幅度裁员之后,大厂裁员消息也开始陆续传出,网易春节前嘎了1600人,游戏线为主,甚至波及到了很多中后台岗位,于是网易散是
软件测试test
10
有一个网络“测试网”悄咪咪达到了70PiB+;还是SSD/Nvme;个人电脑也能参与;
区块链技术的不可能三角是什么?所谓的“不可能三角”即无法同时达到可扩展性(Scalability)、去中心化(Decentralization)、安全(Security)。去中心化:大量区块生产和验证的节点,节点的数量越多,去中心化程度...
IPFS原力区
0
电子书丨《高效自动化测试平台:设计与开发实战》
▊《高效自动化测试平台:设计与开发实战》徐德晨,茹炳晟 著电子书售价:53元2020年06月出版本书从软件自动化测试的发展历史和趋势出发,总结了当前软件自动化测试的需求和挑战,比如:1. 测试对象功能复杂化,...
博文视点Broadview
0