当前位置:首页 > 文章列表 > Golang > Go教程 > Go testing.B RunParallel 如何估计并发吞吐

Go testing.B RunParallel 如何估计并发吞吐

来源:17golang原创 2026-09-15 17:27:37 0浏览 收藏

我第一次用 testing.B.RunParallel 时,最容易误读的是“开了多少个 goroutine”与“每秒完成多少次操作”之间的关系。RunParallel 默认按 GOMAXPROCS 创建 worker,把同一个 b.N 拆给它们;真正要估计并发吞吐,应在并行工作结束后用总迭代次数除以实际计时窗口,而不是拿 worker 数当吞吐。

要点速览
  • pb.Next() 在所有 worker 之间合计执行 b.N 次,b.N 是总操作数。
  • 并发吞吐可按 float64(b.N) / b.Elapsed().Seconds() 估算,再用 ops/s 报告。
  • CPU 密集型任务先比较 -cpu,非 CPU 密集型任务才考虑 SetParallelism(p);并发度提高不保证吞吐线性增长。

先把 RunParallel 的三个数量分开

RunParallel 的 worker 数默认是当前 GOMAXPROCS,调用 SetParallelism(2) 后才变为 2*GOMAXPROCS。这只是参与调度的 goroutine 数。每个 worker 都调用同一个 body,但 pb.Next() 负责从共享迭代计数中领取工作,所以所有 worker 加起来才覆盖 b.N 次操作。

Go testing.B RunParallel 中 GOMAXPROCS、worker、PB.Next 与 b.N 总迭代次数的关系说明图
图1:RunParallel 的并发计数口径说明图,展示 worker 共享总迭代次数,不是运行截图。
含义估计吞吐时的作用
GOMAXPROCS默认并行度基数影响 worker 数,不等于每秒操作数
SetParallelism(p)把 worker 数调为 p*GOMAXPROCS用于等待型或外部依赖型负载的对比
b.N所有 worker 合计完成的迭代数作为吞吐计算的总操作数

在 RunParallel 返回点计算 ops/s

Go 文档明确说明,RunParallel 报告的 ns/op 是整个并行基准的墙上时间,不是各 goroutine CPU 时间相加。要得到更直观的吞吐,可以在 RunParallel 返回后读取 b.Elapsed()。此时所有 worker 已结束,计算结果不会读到中间状态。

func BenchmarkParallelWork(b *testing.B) {
	// 这里的工作体量应保持稳定,避免把随机等待当成吞吐变化。
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			// 每次 Next 代表一次被计入 b.N 的基准操作。
			doWork()
		}
	})

	seconds := b.Elapsed().Seconds()
	if seconds > 0 {
		// b.N 是所有 worker 的总操作数,除以墙上时间得到 ops/s。
		b.ReportMetric(float64(b.N)/seconds, "ops/s")
	}
}

这个指标表达的是“该次基准计时窗口内完成的总操作数/秒”。不要把它解释成单个 goroutine 的速度,也不要把一次短跑的结果当作固定容量。go test -bench BenchmarkParallelWork -cpu=1,2,4 可以观察不同处理器并行度下的变化。

并发度提高后,为什么吞吐可能不再上升

如果 doWork 主要消耗 CPU,继续增加 worker 往往只会带来调度和竞争开销;这类场景通常先用 -cpu 比较。若操作包含网络、磁盘或锁等待,才有理由尝试 SetParallelism,但要同时记录外部服务限流、连接池大小和锁冲突,否则测到的可能只是排队时间。

RunParallel 中并发度、墙上时间、共享资源竞争与 ops/s 输出之间关系的边界说明图
图2:并发度和吞吐的边界关系说明图,区分调度参数、墙上计时和共享资源竞争,不是性能结果截图。
func BenchmarkParallelIO(b *testing.B) {
	// 非 CPU 密集型示例才考虑增加 worker,p 不是吞吐倍率。
	b.SetParallelism(2)
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			// 外部依赖的延迟、连接池和限流都应在结论中单独记录。
			doOneRequest()
		}
	})
	if elapsed := b.Elapsed().Seconds(); elapsed > 0 {
		// 在所有并行调用结束后一次性写入汇总指标。
		b.ReportMetric(float64(b.N)/elapsed, "ops/s")
	}
}

如果还要统计“成功操作数”或字节数,计数器必须使用 atomic.Int64 等并发安全类型,并在返回后读取。不要在 worker 内调用 StartTimerStopTimerResetTimer,这些方法对整个 benchmark 有全局影响。

一张检查表:这个吞吐数字能不能比较

  • 每次 pb.Next() 对应的工作是否一致,是否把初始化误放进计时区间?
  • b.N 是否作为总迭代数使用,而不是乘以 worker 数?
  • 是否记录了 -cpuGOMAXPROCSSetParallelism 和外部资源上限?
  • 是否运行多次并比较趋势,而不是依据单次 ops/s 下结论?

我更愿意把吞吐值当成同一环境下的比较坐标:先固定数据、依赖和基准命令,再改变一个并发参数。如果锁、连接池或服务端限流已经成为瓶颈,继续加并发只是在放大排队,不是在测量真实处理能力。

相关问题

RunParallel 的 b.N 是每个 goroutine 各自的次数吗?

不是。b.N 是整个 benchmark 的总迭代数,pb.Next() 在 worker 之间分配它;计算总吞吐时只使用一次 b.N

SetParallelism(2) 能否说明吞吐提高两倍?

不能。它只把 worker 数调整为 2*GOMAXPROCS,最终速度还受 CPU、锁、连接池、网络和服务端容量影响。

为什么应该在 RunParallel 返回后 ReportMetric?

返回表示并行 body 已完成,此时读取计数和计时结果才是汇总状态;在 worker 内重复上报还会产生覆盖和竞争。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
墨刀AI适合做数据看板原型吗?先验证指标层级、筛选和空状态墨刀AI适合做数据看板原型吗?先验证指标层级、筛选和空状态
上一篇
墨刀AI适合做数据看板原型吗?先验证指标层级、筛选和空状态
Go 包初始化循环为什么在编译期被拒绝
下一篇
Go 包初始化循环为什么在编译期被拒绝
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    42次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    136次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    73次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    35次使用
  • CMMLU中文大模型评估基准:功能、使用教程与应用场景解析
    CMMLU
    深入了解CMMLU中文评估基准,涵盖67个学科主题,提供数据集下载、Zero-shot/Five-shot评估方法及排行榜,助力优化中文语言模型性能。
    23次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码