Go 语言中的基准测试(Benchmark)

384 阅读4分钟

Go 语言中的基准测试(Benchmark)

基准测试(Benchmark)是软件开发中一个非常重要的概念,它可以帮助我们评估代码的性能并进行优化。在 Go 语言中,标准库提供了内置的基准测试框架,使得编写和运行基准测试变得非常简单。在本文中,我们将深入探讨 Go 语言中的基准测试,包括基本用法、示例代码以及如何解读测试结果。

什么是基准测试?

基准测试是一种评估计算机程序性能的方法,它通过测量程序在特定条件下的执行时间、内存使用等指标来进行评估。基准测试通常用于比较不同算法或代码实现之间的性能差异,并帮助开发人员找出程序中的性能瓶颈。

在 Go 语言中,基准测试是通过标准库中的 testing 包来实现的。通过编写基准测试函数并使用特定的命名规范,我们可以轻松地运行基准测试并获取结果。

稳定的测试环境

  1. 保持测试环境稳定:性能测试结果受测试环境的影响很大,因此需要尽可能地保持测试环境的稳定。这包括确保机器处于闲置状态,不要执行其他任务,以及避免和其他人共享硬件资源。
  2. 关闭节能模式:一些笔记本电脑默认会打开节能模式以延长电池寿命,但这会影响性能测试的结果。在进行性能测试时,需要确保关闭节能模式,以保持 CPU 和内存等硬件资源的最佳状态。
  3. 避免使用虚拟机和云主机:虚拟机和云主机为了提高资源利用率,通常会进行资源超分配,这会导致机器性能的不稳定。因此,最好避免在这些环境中进行性能测试,以确保测试结果的准确性和可靠性。

如何编写基准测试?

在 Go 中,编写基准测试非常简单。步骤如下:

  1. 导入 testing 包。
  2. 编写一个以 *testing.B 类型参数作为输入的基准测试函数。
  3. 在基准测试函数中进行测试操作。
  4. 使用 go test 命令运行基准测试。

下面是一个简单的示例,展示了如何编写一个斐波那契数列的基准测试:

package main

import (
	"fmt"
	"testing"
)

func fib(n int) int {
	if n <= 1 {
		return n
	}
	return fib(n-1) + fib(n-2)
}

func BenchmarkFib(b *testing.B) {
	for i := 0; i < b.N; i++ {
		fib(20) // 选择斐波那契数列中的第 20 个数字作为示例
	}
}

func main() {
	fmt.Println("开始执行基准测试...")
}

如何运行基准测试?

go test 命令默认不运行 benchmark 用例的,如果我们想运行 benchmark 用例,则需要加上 -bench 参数。例如:

go test -bench=.

-bench 参数支持传入一个正则表达式,匹配到的用例才会得到执行,例如,只运行以 Fib 结尾的 benchmark 用例:

go test -bench='Fib$' .

benchmark 是如何工作的

benchmark 用例的参数 b *testing.B,有个属性 b.N 表示这个用例需要运行的次数。b.N 对于每个用例都是不一样的b.N*testing.B 结构体的一个属性,用于表示每个基准测试函数的运行次数。测试框架会根据代码的执行时间自动调整 b.N 的值,通常以指数级递增的方式增加。例如,初始值可能是 1,如果测试函数可以在 1 秒内完成,则会逐渐增加到 2、3、5、10、20 等,直到达到一定的时间或次数限制。

$go test .\Fibonacci_test.go -bench='Fib$'         
goos: windows
goarch: 386
cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
BenchmarkFib-8             32734             36364 ns/op
PASS
ok      command-line-arguments  1.677s
  • goos:操作系统,这里是 Windows。
  • goarch:架构,这里是 386,表示 32 位架构。
  • cpu:处理器信息,显示了 CPU 的型号和频率。
  • BenchmarkFib-8:这是一个基准测试函数的名称,-8 表示 GOMAXPROCS,默认情况下等于 CPU 的核数。
  • 32734:表示测试运行了 32734 次。
  • 36364 ns/op:表示每次操作的平均耗时为 36364 纳秒(ns),即每次操作执行的时间。op 是 operation 的缩写。
  • PASS:表示测试通过。
  • ok command-line-arguments 1.677s:显示测试运行的状态和耗时。 ok 表示测试通过,command-line-arguments 是测试包的名称,1.677s 表示测试总耗时为 1.677 秒。

通过运行以上命令,我们可以观察到基准测试的执行过程以及结果。在测试完成后,会输出每次迭代的执行时间等信息,以帮助我们分析代码的性能特征。

结语

通过基准测试,我们可以更好地了解代码的性能特征,并及时发现和解决潜在的性能问题。在进行性能优化时,基准测试是一个非常有用的工具,它可以帮助我们评估改进的效果并做出更好的决策。