当前位置:首页 > 文章列表 > 文章 > linux > Linux perf record定位CPU热点

Linux perf record定位CPU热点

来源:17golang原创 2026-11-15 17:01:33 0浏览 收藏

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。某个函数占比高,表示采样期间程序的指令位置经常落在那里;它值得继续追踪,但不能单独证明这个函数就是唯一根因。

Linux perf record、目标进程、perf_event、CPU采样样本、perf.data和用户内核调用栈之间的静态关系说明图
图1:perf record采样关系说明图,展示目标进程、内核数据接口和perf.data之间的静态关系;这是说明图,不是运行截图。

先把采样范围限定在真正的工作负载

如果可以控制程序的启动方式,优先让 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”容易把符号缺失误判成业务结论。

perf.data经过perf report后形成overhead占比、符号解析、调用链聚合并进入perf annotate的静态关系图
图2:perf report结果解释结构图,展示开销、符号、调用链和源码位置的静态关系;这是说明图,不是运行截图。

调用栈、符号和权限是三道边界

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 里看不到函数名?

常见原因是符号文件缺失、二进制与符号版本不匹配,或调用栈展开条件不足。先处理符号和调用栈,再解释开销百分比。

采样频率是不是越高越好?

不是。更高频率会带来更密集的样本,也可能增加采集开销和数据量。先选择能覆盖问题窗口的频率,再按报告稳定性调整。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Fetch流式读取ReadableStream响应Fetch流式读取ReadableStream响应
上一篇
Fetch流式读取ReadableStream响应
CSSStyleSheet.replaceSync怎样批量更新构造样式
下一篇
CSSStyleSheet.replaceSync怎样批量更新构造样式
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    1039次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1038次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1181次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1143次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    987次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码