Linux bpftrace profile怎样按函数聚合CPU样本
来源:17golang原创
时间:2026-11-15 16:51:31 353浏览 收藏
想用 Linux 上的 bpftrace 找 CPU 热点时,profile 探针适合做按固定时间间隔抽样:每个 CPU 到达采样点就记录当前调用栈,再把相同函数或调用栈的样本累加。按函数聚合的关键不是把采样次数当成精确 CPU 秒数,而是先选好采样频率、栈类型和过滤条件,再用样本数量比较热点。
官方地址:https://bpftrace.org/
最小可用思路是:用profile:hz:99触发采样,用ustack()或kstack()作为聚合键,再用 PID、线程名或进程名收窄范围。样本越多只表示在采样窗口内越常出现在采样点,不等同于一次精确的函数耗时测量。
先分清 profile 采样到底统计什么
bpftrace 官方语言文档把 profile 定义为定时采样探针。它可以写成 profile:hz:99、profile:ms:10 或 profile:s:1 等形式;profile 探针按每个 CPU 的指定间隔触发,底层使用 Linux 的 perf events。这里的 99 Hz 是采样节奏,不是目标函数每秒被调用 99 次。
| 表达式 | 含义 | 适合场景 |
|---|---|---|
profile:hz:99 | 按频率触发采样 | 全局热点观察 |
profile:ms:10 | 每 10 毫秒触发 | 直观控制采样周期 |
profile:s:1 | 每秒触发 | 低成本长时间观察 |
interval:s:10 | 每 10 秒执行一次 interval 代码 | 输出或退出控制 |
因此,按函数聚合更接近采样型 profiling:在固定窗口里,某函数出现在栈顶或调用栈中的次数越多,说明它更可能是 CPU 热点。短函数、睡眠间隙、符号缺失和采样频率都会影响观察结果。
用 ustack 或 kstack 建立函数聚合键
最小的用户态聚合写法,是把当前用户态调用栈作为 map 的 key,把每次采样计为 1。下面是静态示例;代码只表达写法,不声称已经在本机执行。
profile:hz:99
{
// 把用户态调用栈作为聚合键,每次采样增加一个样本
@[ustack()] = count();
}
如果更关心内核路径,可以把聚合键换成 kstack();如果只想先看进程级分布,则可以按 comm 聚合:
profile:hz:49
{
// 先按进程名聚合,低频率用于快速找出可疑进程
@[comm] = count();
}
ustack() 回答用户程序从哪里消耗了采样点,kstack() 回答内核路径从哪里消耗了采样点,而 comm 只回答哪个进程名更常出现在采样点。排查时通常先从 comm 找范围,再切换到用户态或内核态栈。

用 PID 过滤,再观察目标进程的调用栈
全机采样很容易被后台服务和内核线程淹没。已知目标进程 PID 时,可以在 probe 后面加条件,只保留该进程的样本:
profile:hz:99 /pid == 1234/
{
// 只统计目标 PID 的用户态栈,避免其他进程污染结果
@[ustack()] = count();
}
如果要按线程观察,可以使用 tid 作为一层 key,再配合用户态栈:
profile:hz:49 /pid == 1234/
{
// 第一层区分线程,第二层保留用户态调用栈
@[tid, ustack()] = count();
}
PID 过滤只限制采样事件中的当前进程,不会自动把子进程纳入统计;线程很多时把 tid 放进 key 会增加 map 基数;输出出现地址或 unknown 也不代表 profile 没有触发。
采样频率和运行窗口怎么选
频率越高,单位时间内样本越多,但观测成本、map 更新压力和输出体积也会增大。可以按这个顺序收敛:先用 49 Hz 左右摸底,再用 PID 或进程过滤,只有需要观察短函数或瞬时尖峰时才提高频率并缩短窗口。
# 先确认 bpftrace 版本;发行版文档应与实际版本对应 bpftrace --version # 运行示例脚本并以短窗口观察;按 Ctrl-C 结束并输出 map # ./cpu-profile.bt 只是示例脚本路径,不是固定系统路径 sudo bpftrace ./cpu-profile.bt
不要把采样频率机械地换算成函数占用百分比。均匀采样时,样本占比可以作为 CPU 热点的近似比较;调度、阻塞、符号化失败、CPU 亲和性和多进程竞争都会改变解释。对比两次采样时,应保持频率、窗口、过滤条件和负载一致。

读懂 map 输出和符号化限制
脚本结束时,bpftrace 会打印非空 map。对 @[ustack()] = count() 来说,每组调用栈后的数字是该栈被采到的次数;对 @[comm] = count() 来说,数字是进程名对应的采样次数。它们都应被称为样本数,而不是函数调用次数或精确 CPU 时间。
| 现象 | 优先解释 | 下一步 |
|---|---|---|
| 某个栈样本数高 | 该栈在窗口更常出现 | 保持条件重复或延长窗口 |
| 只看到地址或 unknown | 符号表、权限或栈展开不足 | 检查符号包、构建选项和版本 |
| map 项很多 | 聚合键过细或窗口过大 | 先按 comm、PID 收敛 |
| 用户态栈为空 | 用户栈无法展开或过滤不匹配 | 分别检查过滤与符号条件 |
如果需要控制输出频率,可以把观测和输出控制分开:profile 负责累加样本,interval 负责周期性打印或清理 map。不要在每个采样点直接打印文本,否则大量输出会改变被观测程序的行为。
一套可复用的排障顺序
- 确认探针触发:先用
comm或简单计数确认 profile 事件能产生数据。 - 确认范围:检查 PID、线程和 CPU 范围,没有把后台任务误当目标。
- 匹配栈类型:用户态问题用
ustack,内核路径用kstack。 - 处理符号:地址解析失败时先处理符号和权限,再讨论函数热点。
- 重复采样:用相同负载和参数重复采样,避免只依赖一次短窗口。
一个函数样本数高,可能是它本身慢,也可能是它被许多路径共同调用;需要结合调用栈上下文、输入负载和阻塞状态继续分析。
常见问题
profile 统计的是函数调用次数吗?
不是。它按时间点采样当前执行上下文,聚合的是样本出现次数。调用很多但执行极短的函数,未必比少量但执行较久的调用得到更多样本。
为什么 99 Hz 不是每秒恰好 99 个样本?
profile 按每个 CPU 的节奏触发,CPU 数、调度状态、目标过滤和系统能力都会影响实际可见样本;99 Hz 只是请求的采样频率。
ustack 和 kstack 能放在同一个 map key 里吗?
不建议直接混用。两者描述的地址空间和符号解析边界不同,分开聚合更容易解释;需要对照时分别输出,再按同一窗口比较。
什么时候应该换用 perf 或专用 profiler?
需要成熟调用图、长期采样、复杂用户态符号处理或跨平台分析时,应评估 perf、语言运行时 profiler 或持续观测方案;bpftrace 更适合快速提出清晰的内核或用户态观测问题。
总结
Linux bpftrace 的 profile 探针提供按时间抽样的 CPU 观察入口。以 ustack()、kstack() 或 comm 为聚合键,把样本集中到 map 中,再通过 PID、线程和运行窗口逐层收敛,就能快速找出值得继续分析的函数路径。记住样本数是近似信号,不是精确 CPU 时间;频率、符号、过滤条件和重复窗口决定结论是否可信。
-
308 收藏
-
249 收藏
-
380 收藏
-
167 收藏
-
484 收藏
-
227 收藏
-
173 收藏
-
267 收藏
-
文章 · linux | 16小时前 | 命令行工具 · linux运维 · 故障排查 · Linux systemd journalctl 日志排查 启动日志 Boot ID systemd-journald311 收藏
-
文章 · linux | 16小时前 | linux运维 · 文件系统 · Linux 文件句柄 name_to_handle_at open_by_handle_at file_handle mount_id340 收藏
-
351 收藏
-
490 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习