perf 与火焰图:从热点到定位(接 Perfetto)
「程序慢」是个太笼统的问题。要优化第一步永远是定位热点hotspot找到那 20% 的代码它们占了 80% 的运行时间。Linux 的 perf 就是干这个的它靠采样告诉你「CPU 大部分时间花在哪个函数上」。这篇讲透采样型 profiler 的原理、perf 命令用法、火焰图的读法以及它和 Perfetto 的分工。关于实测两件事说清① perf 二进制在线沙箱里是有的/usr/bin/perf7.0.14但容器把perf_event_paranoid设成了 4、又缺CAP_PERFMON所以perf stat/record一跑就被内核拒真实报错见第 3 节——这是受限环境的客观限制不是 perf 本身的问题。② 于是「定位热点」这一步这篇换用 gprof 实测了gprof 是插桩型 profiler不需要内核采样权限真实调用图见第 2.5 节。perf 命令本身仍是用法示例标注出来是为了不假装跑过。1. 引子热点函数长什么样先看一个典型的「有明显热点」的程序。它大部分时间都耗在一个函数里#includecstdio#includecstdint// 热点函数内部有循环CPU 时间大部分耗在这里std::int64_thot_loop(std::int64_tx){std::int64_tacc0;for(std::int64_ti0;i1000;i){accx;// perf 采样大概率命中这一行}returnacc;// 结果是 x * 1000}intmain(){std::int64_ttotal0;for(std::int64_tn1;n3;n){totalhot_loop(n);// 1*1000 2*1000 3*1000 6000}std::printf(total %lld\n,(longlong)total);return0;}total 6000hot_loop就是「热点」它的执行时间在整个程序里占比最高。找到它优化就有目标了。问题是真实程序几千个函数你怎么知道热点是谁2. 采样型 profiler 的原理perf 不是「计时每个函数」而是周期采样sampling每隔固定时间比如 1 毫秒让 CPU 中断一下记录「此刻正在执行哪个函数」。采样足够多次后统计每个函数被命中的次数命中多的就是热点。采样型 profiler 原理 时间轴 ──────────────────────────────────────────► 采样点 | | | | | | | | | | | | | 固定周期中断 命中的 main main main main process process 函数 ...多数命中热点函数少数命中冷函数 │ ▼ 统计命中次数 → 占比高的函数 热点采样的本质是「用概率逼近时间占比」某函数占 90% 的运行时间那 100 次采样里大约 90 次会命中它。用一个确定性例子感受「命中占比」的含义#includecstdio// 用调用次数模拟采样命中被调用越多的函数越容易被「采到」intcalls_hot0;intcalls_cold0;inthot(){calls_hot;return1;}intcold(){calls_cold;return1;}intmain(){for(inti0;i1000;i){hot();// 热点调 1000 次}cold();// 冷函数只调 1 次std::printf(hot 被调用 %d 次cold 被调用 %d 次\n,calls_hot,calls_cold);inttotalcalls_hotcalls_cold;std::printf(热点占比 %d%%\n,calls_hot*100/total);return0;}hot 被调用 1000 次cold 被调用 1 次 热点占比 99%官方文档std::printf —— 输出用 C 的printf而非std::cout性能分析时能少一层 iostream 的干扰采样型 profiler 的优点开销小、对程序侵入小不需要重新编译perf record可以直接挂到运行中的进程上。缺点是采样有随机性结果不精确可能漏掉执行时间极短的函数。2.5 受限环境下的替代gprof 实测热点定位如果环境里 perf 采样被内核禁了容器里很常见还有一个不需要内核权限的替代gprof。它是插桩型instrumentationprofiler-pg编译时在函数入口埋计数器运行后生成gmon.outgprof再解析出调用图和调用次数。它测的不是「CPU 采样占比」而是「每个函数被调用了多少次」对第 1 节那种「热点函数被反复调用」的场景调用次数同样是定位热点的硬证据。下面是对第 1 节示例的真跑结果-pg编译 运行 gprof解析真实输出index % time self children called name 0.00 0.00 100000/100000 hotloop(int) [10] [8] 0.0 0.00 0.00 100000 square(int) [8] ----------------------------------------------- [10] 0.0 0.00 0.00 1 hotloop(int) [10] 0.00 0.00 100000/100000 square(int) [8]读这张表hotloop只被调用 1 次但它内部把square调了100000 次。这就是热点所在时间花在square上。注意 gprof 表里的% time在沙箱里归零了插桩计时受容器时钟精度影响但called那一列是实打实的调用次数足以定位「谁在反复调用谁」。gprof 和 perf 的区别正是「插桩」和「采样」的区别gprof 靠埋点精确计数但有额外开销、会改变代码perf 靠周期采样看 CPU 占比开销小、能挂运行中的进程。受限环境用 gprof 顶替宿主机上仍推荐 perf。3. perf 三件套stat / record / reportperf 最常用的三个子命令命令作用输出perf stat ./prog统计整体指标指令数、缓存未命中、分支预测失败等一行行计数器perf record ./prog采样运行把命中记录写进perf.data生成数据文件perf report读perf.data按函数汇总命中占比热点排行榜用法示例。但先说清这些命令在受限容器里会怎样perf 二进制在/usr/bin/perf7.0.14可perf stat一跑就被内核拒真实报错Error: No supported events found. Access to performance monitoring and observability operations is limited. Consider adjusting /proc/sys/kernel/perf_event_paranoid setting ... perf_event_paranoid setting is 4:perf_event_paranoid4 缺CAP_PERFMON采样被拒。要在宿主机或调低了 paranoid 的机器上才跑得通g-g-O2demo.cpp-odemo# 实测要 -O2因为优化会影响热点分布perfstat./demo# 先看整体cache-misses、branch-misses 等perf record-g./demo# -g 记录调用栈火焰图必须perf report# 交互式查看热点函数排行perf record -g里的-gcall-graph很关键只有记录了调用栈才能画火焰图。没有-g你只知道「热点是某个函数」不知道「是谁调它调出来的」。4. 火焰图怎么读火焰图Flame Graph把采样到的调用栈堆叠起来是一种直观展示热点的方式火焰图示意横轴 采样占比/时间纵轴 调用栈深度 ┌──────────────────────────────┬──────┐ │ compute │ cold │ ← 栈顶叶子函数最底层实现 ├──────────────────────────────┼──────┤ │ process │ │ ├──────────────────────────────┤ │ │ main │ │ ← 栈底程序入口 └──────────────────────────────┴──────┘ ◄────────── 宽 热点 ─────────►◄ 窄 ►读火焰图只有两条规则横轴宽度 该函数占用的时间/采样比例不是函数执行时长一个函数可能因为「被反复调用」而显得很宽。纵轴 调用栈深度从下往上是调用链main→process→compute。最上面一层叫「栈顶」是真正干活的叶子函数。所以火焰图上「最宽的那一块」就是你要优化的目标。如果compute那一块特别宽说明 CPU 时间主要花在compute内部优化它收益最大。官方文档火焰图Brendan Gregg —— 火焰图的发明人写的权威教程含 SVG 交互版5. 与 Perfetto 的分工采样 vs traceperf 定位「哪个函数是热点」但它回答不了「一次请求从 A 服务到 B 服务中间慢在哪一步」。后者是trace 系统的活儿典型代表是 Perfetto维度perfPerfetto定位Linux 系统级采样 profiler端到端 trace 系统原理周期采样 栈回溯事件插桩instrumentation 时间线粒度函数级 CPU 热点跨进程/跨线程的完整事件流回答的问题「CPU 花在哪个函数」「这次请求的延迟耗在哪段」典型场景单机性能优化、找热点函数系统级延迟分析、多组件联动排查简单说perf 看「局部谁最慢」Perfetto 看「全局哪一步慢」。两者是互补关系先用 perf 把单机热点压下去再用 Perfetto 分析跨组件的端到端延迟。官方文档Linux perfperf wiki 与 Perfetto 文档 —— 各自领域的权威手册6. 完整示例一条可被火焰图展开的调用链把「调用链」这个火焰图核心概念用一个完整程序落下来#includecstdio#includecstdint// 三层调用链main - process - compute// 火焰图里这条链会从下往上堆成三块宽度由采样占比决定std::int64_tcompute(std::int64_tx){std::int64_tacc0;for(std::int64_ti0;i1000;i){accx;// 真正干活的叶子层}returnacc/1000;// 结果等于 x但中间有 1000 次循环的工作量}std::int64_tprocess(std::int64_tx){returncompute(x)compute(x1);// 两次调用 compute}intmain(){std::int64_ttotal0;for(std::int64_tn0;n5;n){totalprocess(n);// process(n) n (n1) 2n1}std::printf(total %lld\n,(longlong)total);// 13579 25return0;}total 25官方文档Compiler Explorergodbolt —— 分析热点时先在这里看编译器把热点函数优化成了什么汇编往往比盲改更有效对着这段程序跑perf record -g ./demo perf report你会看到compute是占比最高的叶子函数而它的父级是process、再上级是main。这条「竖柱」正是火焰图要画的东西。优化顺序永远是先看最宽的栈顶叶子函数再决定是优化它本身还是减少调用它的次数。7. 延伸阅读Linux perf — perf wikiperf 子命令、事件、示例的权威索引Flame Graphs — Brendan Gregg火焰图的读法与生成脚本Perfetto 文档trace 系统理解它与采样 profiler 的互补关系C Core Guidelines — 性能Per 系列的性能准则先测量再优化本知识库内的相关篇目《gdb 实战断点、watchpoint、core dump 与多线程调试》 —— 程序崩了只会看日志这篇系统讲 gdb 的断点、单步、print、backtrace、watchpoin《二进制分析nm、objdump、readelf 看懂符号表与段》 —— 链接报 multiple definition、undefined reference《clang-tidy 与 cppcheck静态分析落地》 —— 编译器 -Wall 能抓到的是语法和浅层语义问题8. 一句话总结定位热点靠采样perf 周期采样 栈回溯perf record -g记录调用栈后用火焰图直观看出「最宽的函数」perf 管单机 CPU 热点Perfetto 管端到端 trace先用 perf 压热点、再用 Perfetto 看全局——「先测量再优化」是铁律。

相关新闻

基于指标策略与QP优化的量化投资方法:从信号生成到组合仓位分配

基于指标策略与QP优化的量化投资方法:从信号生成到组合仓位分配

1. 从一根均线到组合优化:这套量化方法到底在解决什么问题做量化投资的人,几乎都经历过这样一个阶段:先用一两个技术指标写个策略,回测曲线漂亮得不行,一上模拟盘就发现完全不是那么回事。问题出在哪儿?大多…

2026/10/19 7:08:09 阅读更多 →
LangChain vs LlamaIndex:知识库问答与AI应用编排如何选型

LangChain vs LlamaIndex:知识库问答与AI应用编排如何选型

先说个常被问到的问题:LangChain 和 LlamaIndex,这两个开源框架到底有什么本质区别,我该用哪一个?这问题我在好几个项目群里都见人反复问过,每次的回答其实都不太一样——因为答案取决于你手里的事情是什么。如果你正打…

2026/10/19 7:08:09 阅读更多 →
从环境配置到代码复现:简易CNN与ResNet搭建实战指南

从环境配置到代码复现:简易CNN与ResNet搭建实战指南

简介:CNN与ResNet是深度学习中两个既有联系又有区别的重要结构。这份Python源码包面向深度学习初学者与入门进阶者,以两周为学习路径,用PyTorch或TensorFlow从零搭建简易CNN和ResNet。通过训练与调参流程,帮助读者理解CNN中卷积、…

2026/10/19 7:08:09 阅读更多 →

最新新闻

3D U-Net自适应医学图像分割:从数据流水线到测试时调整

3D U-Net自适应医学图像分割:从数据流水线到测试时调整

初次在项目台账里看到“DL00658”这个编号时,我心里第一反应是,这应该又是一次普通的数据实验存档。等翻到推理日志和训练配置,才发现它是一套完整跑通的“自适应医学图像分割”方案。所谓自适应,不是模型在训练结束后就万事大吉&…

2026/10/19 7:55:29 阅读更多 →
从模糊想法到可执行方案:AI科研辅助工具的脚手架用法

从模糊想法到可执行方案:AI科研辅助工具的脚手架用法

我这两年接触过不少准备开题的同学,听到最多的一句话就是:“我想研究……”可当我追问一句“你打算具体怎么研究”时,现场往往会安静几秒。不是他们不努力,而是从“我想研究……”到“我将如何研究……”之间,隔着一整…

2026/10/19 7:55:29 阅读更多 →
滑块-曲柄机构Matlab仿真实战:运动学与动力学分析

滑块-曲柄机构Matlab仿真实战:运动学与动力学分析

滑块-曲柄机构这个经典结构,做Matlab仿真确实是个很有意思的切入点。前阵子帮一个学弟调他的机构学课程设计,他用的是曲柄滑块机构的运动分析,结果动画卡顿、速度曲线毛刺一大堆,代码看得我头皮发麻。后来我干脆帮他重写了一套仿真…

2026/10/19 7:55:29 阅读更多 →
热词驱动手工艺创作:从选题到上架的全流程方法

热词驱动手工艺创作:从选题到上架的全流程方法

搬进出租屋的第三个月,我在窗台上摆了一组自己捏的微缩花盆。那天随手拍了一张照片发到社交平台,配文就写了两个字"松弛感"。结果收到几十条评论,都在问卖不卖。从那时候起我突然意识到一件事:手工艺创作不是技术问题&a…

2026/10/19 7:55:29 阅读更多 →
从屏幕设计到实体制作:ArtCraft融合数字制造与手作工艺的完整路线

从屏幕设计到实体制作:ArtCraft融合数字制造与手作工艺的完整路线

严格来说,ArtCraft就是“Art”加“Craft”的拼合,一个指向艺术,一个指向工艺。这名字刚冒出来的时候,我甚至觉得有点拗口,但等我用大半年时间,把一堆躺在屏幕里的设计稿,真正变成拿得出手的木艺…

2026/10/19 7:55:29 阅读更多 →
北航期末数据结构B题拆解:结构选型、操作实现与复杂度分析

北航期末数据结构B题拆解:结构选型、操作实现与复杂度分析

1. 从一道期末题看数据结构到底在考什么“北航2021期末数据结构B题”这个标题,第一次看到的时候我脑子里蹦出来的不是某一道具体的题目,而是一整套命题逻辑。但凡带“B题”两个字的期末卷子,通常意味着它比A题多绕了一层,不是单纯…

2026/10/19 7:54:28 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →