0Pricing
Go Academy · 课时

使用 testing.B 编写基准测试

BenchmarkXxx、b.N 循环与 -bench 标志

使用 testing.B 编写基准测试 是 CoddyKit 上的免费 Go Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

基准测试函数签名

基准测试以 Benchmark 开头,接收 *testing.B。它们与常规测试一起放在 _test.go 文件中运行。

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(2, 3)
    }
}

b.N

测试框架会自动调整 b.N——循环迭代次数——直到基准测试至少运行 1 秒,从而得到稳定的每操作纳秒数。

运行基准测试

仅运行 go test 不会执行基准测试。请使用 -bench 启用基准测试:

go test -bench=. -benchmem ./...
// BenchmarkAdd-8  500000000  2.13 ns/op  0 B/op  0 allocs/op

-benchmem 标志

-benchmem 会添加分配统计信息:每次操作的字节数以及每次操作的分配次数。较高的分配量通常表示存在性能问题。

b.ResetTimer

在不应计入基准测试的昂贵设置操作之后调用 b.ResetTimer():

func BenchmarkQuery(b *testing.B) {
    db := setupDB() // expensive
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        db.Query("SELECT 1")
    }
}

b.StopTimer / b.StartTimer

在不应计入基准测试时间的设置或清理过程前后暂停并恢复计时器。

for i := 0; i < b.N; i++ {
    b.StopTimer()
    data := generateInput()
    b.StartTimer()
    process(data)
}

b.SetBytes

调用 b.SetBytes(n),除了报告每次操作耗时之外,还可以报告吞吐量(字节/秒)。这对于测试序列化或网络代码很有用。

b.SetBytes(int64(len(payload)))
for i := 0; i < b.N; i++ {
    encode(payload)
}

比较基准测试

使用 benchstat 比较两次基准测试运行,并查看具有统计显著性的差异:

go test -bench=. -count=10 > before.txt
# make change
go test -bench=. -count=10 > after.txt
benchstat before.txt after.txt

防止死代码消除

将结果赋给包级变量或接收变量,以防编译器将基准测试代码优化掉:

var result int
func BenchmarkFib(b *testing.B) {
    for i := 0; i < b.N; i++ {
        result = Fib(20)
    }
}

子基准测试

使用 b.Run 创建命名的子基准测试,类似于表驱动测试:

for _, size := range []int{10, 100, 1000} {
    b.Run(fmt.Sprintf("size=%d", size), func(b *testing.B) {
        for i := 0; i < b.N; i++ { sort(make([]int, size)) }
    })
}

基准测试与性能分析

基准测试用于量化性能。性能分析(pprof)显示时间花在哪里。请使用基准测试进行测量,使用性能分析诊断需要优化的位置。

快速检查

为什么基准测试循环体必须使用结果,才能防止编译器优化?

回顾:基准测试

关键要点:

  • BenchmarkXxx(b *testing.B),循环使用 for i := 0; i < b.N; i++
  • 使用 go test -bench=. -benchmem 获取分配统计信息
  • 在昂贵的设置操作之后调用 b.ResetTimer()
  • 使用 benchstat 比较运行结果;赋值结果以防止代码被消除

常见问题解答

「使用 testing.B 编写基准测试」课时是免费的吗?

是的 — 「使用 testing.B 编写基准测试」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「使用 testing.B 编写基准测试」这节课中我会学到什么?

BenchmarkXxx、b.N 循环与 -bench 标志 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「使用 testing.B 编写基准测试」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 testing.B 编写基准测试
  2. 使用 pprof 进行 CPU 性能分析
  3. 堆与内存分配性能分析
  4. 执行跟踪
← 返回 Go Academy