Golang 基准测试(Benchmark)

简介: 在程序中,基准测试,是一种测试代码性能的方法;比如有一个问题你有多种不同的方案,你想选择一种性能最好的方案,那么你就需要基准测试。

Benchmark 🧪

基准测试是对计算机系统的性能的测试。

在程序中,基准测试,是一种测试代码性能的方法;比如有一个问题你有多种不同的方案,你想选择一种性能最好的方案,那么你就需要基准测试。

基准测试主要是通过测试 CPU 和内存的效率问题,来评估被测试代码的性能,进而找到更好的解决方案。比如链接池的数量不是越多越好,那么哪个值才是最优值呢,这就需要配合基准测试不断调优了。

工程意图

仓库: https://github.com/guzhongren/TDD/tree/master/09.benchmar

根据输入的字符串和重复次数,输出重复次数后的字符串。

初始化工程

go mod init benchmark

测试的函数需要以 Test 开头,参数为 *testing.T 类型

Test

  • 测试先行
# 测试 Repeat 函数
func TestRepeat(t *testing.T) {
    actual := Repeat(`a`, 6)
    expect := `aaaaaa`
    if actual != expect {
        t.Errorf(`expect %s, but got %s`, expect, actual)
    }
}
  • 运行 go test, 程序会报错,因为没有实现 Repeat 函数。
  • 最小化的实现 Repeat
// Repeat return a string with same char
func Repeat(char string, count int) (result string) {
    for i := 0; i < count; i++ {
        result += char
    }
    return
}

上面的函数中 return 并没有返回值,是因为,在 Repeat 函数的返回值部分有一个result,
当返回值是函数体里面的值的时候,可以不用写返回值,go 程序自动将该值返回。但return 依旧不能省略。

Benchmark

基准测试的函数名须以 Benchmark 开头, 参数须为 *testing.B;循环中的 b.N, go 会根据系统情况生成,不用用户设定。

func BenchmarkRepeat(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Repeat(`b`, 5)
    }
}

运行测试

  • 基本测试
$ go test
PASS
ok      benchmark       0.006s

基本测试很简单,不用解读了。

  • 基准测试
$ go test -bench=. -run=none
goos: darwin
goarch: amd64
pkg: benchmark
BenchmarkRepeat-12      10000000               116 ns/op
PASS
ok      benchmark       1.297s

运行基准测试也要使用go test命令,不过我们要加上-bench=标记,它接受一个表达式作为参数,匹配基准测试的函数,. 表示运行所有基准测试。

因为默认情况下 go test 会运行单元测试,为了防止单元测试的输出影响我们查看基准测试的结果,可以使用-run=匹配一个从来没有的单元测试方法,过滤掉单元测试的输出,我们这里使用none,因为我们基本上不会创建这个名字的单元测试方法。

下面着重解释下说出的结果,看到函数后面的-12了吗?这个表示运行时对应的 GOMAXPROCS 的值。接着的 10000000 表示运行 for 循环的次数,也就是调用被测试代码的次数,最后的 116 ns/op表示每次需要话费 116 纳秒。
以上是测试时间默认是1秒,也就是1秒的时间,调用 10000000 次,每次调用花费 116 纳秒。如果想让测试运行的时间更长,可以通过 -lunchtime 指定,比如5秒。

目录
相关文章
|
NoSQL 测试技术 Go
Golang周边 | Benchmark性能测试
Golang Benchmark性能测试
246 0
Golang周边 | Benchmark性能测试
|
17天前
|
Go
go语言中的数据类型
go语言中的数据类型
13 0
|
23天前
|
Go 开发者
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
|
23天前
|
安全 Go
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
|
23天前
|
存储 缓存 安全
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
|
4天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南
|
23天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
1天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
10 1
|
1天前
|
人工智能 Go 调度
掌握Go并发:Go语言并发编程深度解析
掌握Go并发:Go语言并发编程深度解析
|
1天前
|
SQL 关系型数据库 MySQL
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程