Golang的标准测试库中提供了RunParallel方法,用于在基准测试中模拟并行执行场景,帮助开发者评估程序在多goroutine并发运行时的性能表现,相比普通串行基准测试,它能更贴近真实的高并发运行环境。

RunParallel的基本使用结构
RunParallel是testing.B结构体的方法,需要在基准测试函数中调用,它的核心作用是启动多个goroutine并行执行测试逻辑,同时自动协调各个goroutine的执行节奏,避免因为启动顺序差异导致测试结果不准确。
基础的使用框架如下:
package main
import (
"sync"
"testing"
)
// 待测试的并行函数
func addParallel(a, b int) int {
return a + b
}
func BenchmarkAddParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
// 每个goroutine会循环执行这个逻辑,直到pb.Next()返回false
for pb.Next() {
addParallel(1, 2)
}
})
}
RunParallel的参数与执行逻辑
RunParallel接收一个函数作为参数,这个函数的参数是*testing.PB类型的实例,通过调用pb.Next()来判断当前goroutine是否还需要继续执行测试逻辑。当pb.Next()返回false时,说明基准测试的迭代次数已经达标,当前goroutine可以退出。
可以通过b.SetParallelism方法设置并行执行的goroutine数量,默认情况下会根据当前机器的CPU核心数自动调整,示例代码如下:
func BenchmarkAddParallelWithCustomGoroutine(b *testing.B) {
// 设置并行goroutine数量为4
b.SetParallelism(4)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
addParallel(3, 4)
}
})
}
带共享状态的并行测试注意事项
如果测试逻辑中需要操作共享状态,必须做好并发安全控制,否则会导致测试结果不准确甚至程序崩溃。常见的做法是使用sync.Mutex或者sync/atomic包中的原子操作来保证安全。
下面是错误的共享状态使用示例,会引发并发问题:
var sharedCount int
func BenchmarkSharedStateWrong(b *testing.B) {
sharedCount = 0
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// 多个goroutine同时修改sharedCount,存在竞态问题
sharedCount++
}
})
}
正确的带共享状态的测试示例如下:
import "sync/atomic"
var safeCount int64
func BenchmarkSharedStateCorrect(b *testing.B) {
atomic.StoreInt64(&safeCount, 0)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// 使用原子操作保证并发安全
atomic.AddInt64(&safeCount, 1)
}
})
}
RunParallel的常见使用误区
- 不要在RunParallel的回调函数中再次启动新的goroutine,RunParallel本身已经管理了并行goroutine的创建和调度,额外启动goroutine会干扰测试逻辑。
- 不要在
pb.Next()循环外部写测试逻辑,RunParallel只会统计循环内部的执行耗时,外部逻辑不会被计入基准测试结果。 - 如果测试逻辑有初始化操作,可以在RunParallel之前完成,或者每个goroutine内部自行初始化独立的变量,避免共享初始化状态。
运行并行基准测试的命令
编写好基准测试代码后,使用以下命令运行并行基准测试:
# 运行所有基准测试,输出并行测试结果 go test -bench=. -benchmem
命令中的-benchmem参数可以额外输出内存分配相关的统计信息,帮助更全面地评估并行场景下的性能表现。
GolangRunParallel并行基准测试benchmark修改时间:2026-06-27 22:15:41