如何在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; ?>
】
相关推荐
- Python模块的__name__属性如何由导入方
- Win11怎么关闭开机声音_Win11系统启动提示
- Win11关机界面怎么改_Win11自定义关机画面
- Win11怎么设置开机密码_Windows11账户
- Win11怎么关闭贴靠布局_Win11禁用窗口最大
- 如何在Golang中解压文件_Golang com
- Windows 11如何开启文件夹加密(EFS)_
- Win11怎么设置环境变量_Win11配置Path
- Win11怎么更改电脑密码_Windows 11修
- 如何在 Go 同包不同文件中正确引用结构体
- Win11笔记本怎么看电池健康度_Win11电池报
- Python多进程教程_multiprocessi
- 微信里的php文件怎么变mp4_微信接收php转m
- C++如何使用std::transform批量处理
- Win10如何卸载微软拼音输入法 Win10只保留
- PHP 中 require() 语句返回值的用法详
- Windows系统时间服务错误_W32Time服务
- Win10如何备份驱动程序_Win10驱动备份步骤
- Win11怎么更改鼠标指针方案_Windows11
- Win11怎么打开注册表_Windows 11注册
- 如何在Golang中操作嵌套切片指针_Golang
- XSLT怎么生成动态的HTML属性名和标签名
- Windows如何拦截2345弹窗广告_Windo
- Win11怎么设置ip地址_Windows 11手
- 如何在 Go 中高效缓存与分发网络视频流
- Windows10系统怎么查看CPU温度_Win1
- Win11怎么设置虚拟内存_Windows 11优
- Win10如何优化内存使用_Win10内存优化技巧
- Python函数参数高级用法_默认值与可变参数解析
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- Win11怎么开启智能存储_Windows11存储
- php打包exe如何加密代码_防反编译保护方法【技
- php订单日志怎么记录评价_php记录订单评价日志
- Win11怎么关闭键盘按键音_Win11禁用打字声
- 一文教你快速开通网站LOGO图
- 如何使用正则表达式精确匹配最多含一个换行符的 st
- Win11怎么更改电脑名称_Windows 11修
- c++怎么操作redis数据库_c++ hired
- Win11怎么查看显卡温度 Win11任务管理器查
- Windows 10怎么录屏_Windows 10
- Windows资源管理器总是卡顿或重启怎么办?(修
- TestNG的testng.xml配置文件怎么写
- php485返回数据不完整怎么办_php485数据
- php订单日志怎么记录发货_php记录订单发货操作
- 如何解决Windows时间不准的问题?(自动同步设
- Laravel 查询 JSON 列:高效筛选包含数
- PythonPandas数据分析项目教程_时间序列
- Win10系统更新错误0x80240034怎么办
- 如何在Golang中处理云原生事件_使用Event
- php文件怎么变mp4保存_php输出视频流保存为

QQ客服