如何在Golang中实现自定义Benchmark_Golang testing.B自定义性能测量示例
技术百科
P粉602998670
发布时间:2026-01-01
浏览: 次 自定义 Benchmark 函数必须命名为 BenchmarkXxx,接收 *testing.B 参数,通过 go test -bench=. 运行;需在 b.N 循环外初始化并调用 b.ResetTimer(),避免测量初始化开销。
如何在 Go test 文件中定义并运行自定义 Benchmark 函数
Go 的 testing.B 是唯一合法的 benchmark 入口,所有自定义性能测量必须以 BenchmarkXxx 形式定义,且函数签名固定为 func(*testing.B)。它不是普通函数调用,不能手动传参或直接执行——必须通过 go test -bench=.
触发。
常见错误是把 benchmark 写成普通函数、漏掉 b.ResetTimer()、或在 b.N 循环外做初始化却未排除耗时,导致结果失真。
- 函数名必须以
Benchmark开头,首字母大写 - 必须接收单个
*testing.B参数 - 循环体必须用
for i := 0; i ,不可硬编码次数 - 预热或初始化逻辑应放在
for循环之前,并调用b.ResetTimer()重置计时起点
为什么必须调用 b.ResetTimer() 和 b.StopTimer()
Go 默认从函数入口开始计时,但初始化(如构造 map、读配置、建连接)不属于被测逻辑。若不干预,这些开销会污染 b.N 循环的平均耗时。
b.ResetTimer() 重置计时器,把后续 b.N 循环作为唯一测量区间;b.StopTimer() 暂停计时,适合在循环中穿插非关键操作(如日志打印、临时缓存清理),避免干扰核心路径。
- 初始化后、循环前调用
b.ResetTimer()是最常见且必要的操作 - 若循环体内需执行不可省略但非目标逻辑(如 sync.Pool Get/Pool),可用
b.StopTimer()+b.StartTimer()包裹 - 忘记
ResetTimer()会导致 benchmark 报出极低 QPS、极高 ns/op,数值完全不可比
如何测量不同输入规模下的性能变化(如 slice 长度递增)
标准 testing.B 不支持参数化 benchmark,但可通过闭包或子测试方式模拟多组输入。推荐在单个 Benchmark 函数内遍历不同规模,对每组调用 b.Run() 创建子 benchmark,便于横向对比。
注意:每个 b.Run() 子项独立计时,且会继承父项的 -benchmem 等标志,适合观察增长趋势。
func BenchmarkCopySlice(b *testing.B) {
sizes := []int{100, 1000, 10000}
for _, n := range sizes {
b.Run(fmt.Sprintf("Len%d", n), func(b *testing.B) {
data := make([]byte, n)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = append([]byte(nil), data...)
}
})
}
}
如何安全地在 benchmark 中使用并发(b.RunParallel)
b.RunParallel 用于模拟多 goroutine 并发调用同一逻辑,适用于测试锁竞争、channel 吞吐、sync.Pool 等场景。但它不保证总执行次数为 b.N,而是将 b.N 拆分给多个 goroutine 并行执行——实际调用次数 ≥ b.N,且无法控制 goroutine 数量(由 runtime 自动调度)。
关键约束:被测函数不能依赖共享可变状态,否则结果不可复现;所有初始化必须在 b.RunParallel 外完成。
- 传入的
func(*testing.PB)中,pb.Next()控制是否继续,必须用for pb.Next() { ... }循环包裹被测逻辑 - 不要在
pb.Next()循环内做初始化(如 new struct、open file),这会放大资源开销 - 并发 benchmark 的内存分配统计(
-benchmem)反映的是单次调用均值,不是总和
func BenchmarkConcurrentMapSet(b *testing.B) {
m := make(map[int]int)
var mu sync.RWMutex
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
mu.Lock()
m[1] = 1
mu.Unlock()
}
})
}
Go benchmark 的真实难点不在写法,而在于区分“测什么”和“怎么排除干扰”。比如 time.Now() 调用本身有开销,fmt.Sprintf 在循环里会掩盖核心逻辑性能,甚至 GC 周期都可能让结果抖动——这些都需要靠多次运行、关闭 GC(debug.SetGCPercent(-1))、或结合 pprof 进一步定位。
# 的是
# 放在
# 能让
# 多个
# 极高
# 适用于
# 自定义
# 计时器
# app
# 不支持
# go
# golang
# 循环
# 并发
# 编码
# 为什么
# 继承
# Struct
# map
# channel
# 闭包
# 遍历
# for
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- MAC如何安装Git版本控制工具_MAC开发环境配
- Mac如何使用听写功能_Mac语音输入打字【效率技
- 如何在Golang中实现CI/CD流水线自动化测试
- Win11怎么关闭触控板_Win11笔记本禁用触摸
- Win11无法识别耳机怎么办_解决Win11插耳机
- Win11怎么关闭SmartScreen_禁用Wi
- 如何在Golang中写入XML文件_生成符合规范的
- mac怎么打开终端_MAC终端Terminal使用
- 如何使用Golang管理模块版本_Golanggo
- 如何在Golang中实现基础配置管理功能_Gola
- Win11怎么连接蓝牙耳机_Win11蓝牙设备配对
- 使用类变量定义字符串常量时的类型安全最佳实践
- 如何使用Golang sync.Map实现并发安全
- Python多线程使用规范_线程安全解析【教程】
- 如何用正则表达式精确匹配最多含一个换行符的起止片段
- php串口通信波特率怎么选_根据硬件手册设置正确波
- MySQL 中使用 IF 和 CASE 实现查询字
- Go 语言标准库为何不提供泛型切片的 Contai
- Win10怎样设置闹钟贪睡时间 Win10闹钟贪睡
- 如何使用Golang encoding/json解
- Win11怎么开启自动HDR画质_Windows1
- 如何使用Golang安装API文档生成工具_快速生
- Windows怎样关闭桌面弹窗广告_Windows
- Windows10系统怎么查看系统版本_Win10
- Win11任务栏怎么固定应用 Win11将软件图标
- Win11开机自检怎么关闭_跳过Win11开机磁盘
- c# F# 的 MailboxProcessor
- php删除数据怎么清空表_truncate与del
- 如何提升Golang JSON序列化性能_Gola
- Win11怎么关闭内容自适应亮度_Windows1
- Win11怎么关闭边缘滑动手势_Windows11
- 如何高效删除 NumPy 二维数组中所有元素相同的
- Bpmn 2.0的XML文件怎么画流程图
- Win11如何更新显卡驱动 Win11检查和安装设
- Windows服务无法启动错误1067是什么_进程
- Win11怎么格式化U盘_Win11系统U盘格式化
- windows系统如何安装cab更新补丁_wind
- 短链接怎么用php递归还原_多层加密链接的处理法【
- Windows10系统怎么查看防火墙状态_Win1
- c++ namespace命名空间用法_c++避免
- Windows10系统怎么查看显卡型号_Win10
- Windows10如何更改计算机工作组_Win10
- php怎么操作Redis_Redis扩展连接与基本
- php嵌入式日志记录怎么实现_php将硬件数据写入
- MAC如何设置网卡MAC地址克隆_MAC终端修改物
- PHP的Workerman对架构扩展有啥帮助_应用
- Mac如何设置动态壁纸?(让桌面动起来)
- Win11如何设置自动关机 Win11定时关机命令
- 如何使用Golang管理跨项目依赖_Golang多
- Python文件操作优化_大文件与流处理解析【教程

QQ客服