Linux perf record定位CPU热点
Linux 上遇到某个服务 CPU 长时间偏高时,我通常先用 perf record 做一段带调用栈的采样,再用 perf report 按开销占比看热点函数。它记录的是一组采样样本,不是“已经找到根因”的结论;真正有用的结果来自明确的采样范围、完整的符号和对调用链的再次判断。
官方文档:https://www.kernel.org/doc/html/latest/
最小闭环可以记成:针对一个已知工作负载运行perf record -F 99 -g -- ./your-program,生成perf.data,然后用perf report --stdio找到高开销函数,再决定是否进入perf annotate或代码级排查。
perf record 到底记录了什么
perf record 会启动或附着到目标任务,利用内核的 perf 事件接口收集采样,并把结果写入 perf.data。加上 -g 后,样本还会带上用户态和内核态调用栈,后续报告才有机会回答“热点函数是从哪条调用链过来的”。
因此,perf record 的直接产物是采样数据,perf report 才负责读取并呈现 profile。某个函数占比高,表示采样期间程序的指令位置经常落在那里;它值得继续追踪,但不能单独证明这个函数就是唯一根因。

先把采样范围限定在真正的工作负载
如果可以控制程序的启动方式,优先让 perf record 包住一次明确的请求、批处理或压测场景。下面的命令使用软件时钟事件和调用栈,输出文件名也显式写出,方便和不同场景的报告对应。
# -F 控制采样频率,-g 保存调用栈;-- 后面是要分析的目标程序 perf record -F 99 -g -o perf.data -- ./your-program --workload sample # 读取刚生成的 profile,使用文本界面便于保存到工单或日志 perf report --stdio -i perf.data # 如果还需要看某个函数的源码/汇编位置,再从同一个数据文件进入细化视图 perf annotate -i perf.data
-F 99 是一个常见的起始值,不是固定标准;采样频率越高,观察细节越多,同时也要考虑采集开销和数据体积。-g 会记录调用链,调用链的展开方式还受到程序是否保留帧指针、是否有 DWARF 信息等条件影响。
对于已经运行的进程,可以使用进程号附着,而不是重新启动服务:
# 把 PID 替换成需要观察的进程号,-p 只针对这个已有进程采样 perf record -F 99 -g -p 12345 -o perf.data # 结束采样后从指定文件读取函数开销和调用链 perf report --stdio -i perf.data
附着模式更适合线上短时观察,但要先确认采样窗口内确实发生了目标请求;如果进程处于空闲状态,报告里的“热点”只代表空闲窗口里的活动,不能代表业务高峰。
用 perf report 把样本收敛成热点函数
perf report 读取 perf.data 并展示 profile。刚开始排查时我会先看文本输出,先确认报告里是否有目标进程、事件类型、样本数量和可解析的符号,再看 Overhead 较高的函数。调用链完整时,再把父函数和子函数放在一起判断,避免只盯住一行叶子函数。
# --stdio 输出可复制的报告;--children 让子调用的开销也能汇总到父函数 perf report --stdio --children -i perf.data # -n 显示每个符号对应的样本数量,适合和开销百分比一起看 perf report --stdio -n -i perf.data # perf script 展开原始采样记录,适合需要进一步加工或保留调用链文本时使用 perf script -i perf.data
报告中的函数名依赖符号解析。二进制被裁剪、构建时没有保留可用调试信息、容器里的符号文件与实际运行版本不匹配时,报告可能只显示地址、动态库名或不完整的调用栈。此时继续讨论“谁最耗 CPU”容易把符号缺失误判成业务结论。

调用栈、符号和权限是三道边界
CPU 热点定位最容易卡在三个地方:调用栈收不上来、符号对不上、采样权限不允许。它们分别影响“能否看到上层调用者”“能否把地址翻译成函数名”和“能否开始采样”,排查时不要混为一个问题。
- 调用栈不完整:先看
-g使用的调用图方式。默认的帧指针方式要求程序的栈信息满足对应条件;如果程序省略了帧指针,可以根据发行版和 perf 构建能力考虑--call-graph dwarf,但它会增加栈数据和采集成本。 - 符号显示不全:保留与运行二进制相匹配的符号或调试文件,并让报告使用正确的符号路径。不要把一份旧构建的符号文件拿来解释另一份已部署文件。
- 权限被拒绝:Linux 内核的 perf 安全策略会影响普通用户能观察哪些任务和事件。先查看当前策略和运维规则,不要为了让命令“跑起来”就直接降低全机安全限制。
# 先记录内核当前对 perf 事件的限制,结果只用于判断权限边界 sysctl kernel.perf_event_paranoid # 查看本机 perf 与内核帮助,确认当前构建支持哪些调用图选项 perf version perf record --help | grep -E -- '--call-graph|-F|--pid'
权限、符号和调用栈都正常时,报告才适合进入代码优化;否则更稳妥的做法是先补齐采样条件,再重新采一段与原问题相同的工作负载。
我会怎样把热点报告变成下一步动作
如果报告里某条调用链长期占据较高开销,我会先问三个问题:它是否覆盖了真正的业务窗口?它的父调用者是否也高?它代表的是业务代码、运行时、系统调用还是动态库?这一步的目的不是马上改代码,而是把采样结果和问题现场重新对齐。
| 看到的现象 | 下一步关注点 |
|---|---|
| 单个业务函数占比高且调用栈完整 | 进入源码或 perf annotate,检查循环、锁、序列化和重复计算 |
| 热点集中在动态库或运行时 | 确认输入规模、调用频率和上层业务调用链,不要只改库内部 |
| 大量地址没有函数名 | 先补齐匹配的符号和构建信息,再重新解释报告 |
| 采样结果不稳定 | 固定采样窗口、事件类型和工作负载,比较多次报告中的共同部分 |
和只看一瞬间的 top 相比,perf record 的优势是能把一段工作负载保存下来,后面反复用 perf report、perf script 或 perf annotate 分析;代价是需要更明确地处理采样权限、符号和数据文件管理。
相关问题
perf record 只看一个进程可以吗?
可以。对已有进程使用 -p PID,对新启动的命令则把目标程序放在 -- 后面。两种方式都要保证采样窗口覆盖真正发生 CPU 压力的工作负载。
为什么 perf report 里看不到函数名?
常见原因是符号文件缺失、二进制与符号版本不匹配,或调用栈展开条件不足。先处理符号和调用栈,再解释开销百分比。
采样频率是不是越高越好?
不是。更高频率会带来更密集的样本,也可能增加采集开销和数据量。先选择能覆盖问题窗口的频率,再按报告稳定性调整。
Fetch流式读取ReadableStream响应
- 上一篇
- Fetch流式读取ReadableStream响应
- 下一篇
- CSSStyleSheet.replaceSync怎样批量更新构造样式
-
- 文章 · linux | 36分钟前 | linux运维 · Linux 命名空间 挂载树 Mount API open_tree move_mount
- Linux open_tree怎样复制挂载树
- 376浏览 收藏
-
- 文章 · linux | 43分钟前 | linux运维 · Linux 防火墙规则 nftables nft list ruleset 地址族 规则集导出
- nftables list ruleset怎样按地址族导出配置
- 308浏览 收藏
-
- 文章 · linux | 49分钟前 | linux运维 · 服务管理 · Linux systemd socket激活 systemd.socket systemd.service
- Linux systemd socket激活服务
- 249浏览 收藏
-
- 文章 · linux | 49分钟前 | Linux · Linux systemd Cron Timer OnCalendar
- Linux systemd定时器替代cron任务
- 380浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 1039次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 1038次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 1181次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 1143次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 987次使用
-
- Linux vmstat 如何分辨内存抖动与磁盘等待:si、so、wa 与复测顺序
- 2026-08-30 501浏览
-
- Linux搭建vsftpdFTP服务器教程
- 2026-04-30 501浏览
-
- Shell脚本安装教程:.sh一键安装指南
- 2026-03-16 501浏览
-
- Linux清空文件内容的几种方法
- 2025-12-01 501浏览
-
- Linux命令行下载文件技巧
- 2025-11-23 501浏览

