工具会用不等于能定位问题。很多人手里攥着top、iostat、sar遇到「系统慢」还是乱敲一通看哪儿都像瓶颈。真正的高手靠的是方法论——一套「怎么切入、按什么顺序查、如何验证」的框架。这一篇讲透性能分析的两大方法论USE 和 RED、火焰图的原理与实战帮你从「工具体力活」升级到「思路技术活」。一、为什么需要方法论先看一个典型的反面教材程序员小李接到告警「接口超时」。他登录机器敲了 top 看到 CPU 10%觉得没问题又看 free内存也够 最后猜是「网络抖动」重启了服务。问题暂时好了 第二天又来了。没有方法论的排查就是靠猜和重启。有方法论的人会这样走先明确「慢」的定义是哪个接口、P99 多少、从何时开始。按 USE 检查物理资源CPU、内存、磁盘、网络有没有饱和。按 RED 检查服务本身请求量、错误率、延迟。用perf 火焰图钻到代码热点。找到根因改然后用数据验证。方法论的价值在于保证覆盖、减少遗漏、可复现、可解释。下面两个框架是业界公认的两把尺子。二、USE 方法面向资源USE Utilization使用率、Saturation饱和度、Errors错误由 Brendan Gregg 提出专门用来系统性地检查每一类资源。对系统里的每种资源依次问三个问题使用率资源有多忙如 CPU 80% 忙饱和度有多少工作在排队如运行队列长度错误有报错吗如网卡丢包、磁盘错一张表覆盖所有资源资源使用率饱和度错误CPUmpstat的%usr%sysvmstat的r列dmesg里 MCE内存free的 usedvmstat的si/so、OOMdmesg的 OOM磁盘iostat的%utiliostat的aqu-szsmartctl、dmesg网络sar -n DEV带宽ss的Recv-Q、重传netstat -s错误文件描述符ls /proc/pid/fd \| wc -l—Too many open files实战一步一步走 USE# 1. CPU 使用率 饱和度 mpstat -P ALL 1 3 # 使用率 vmstat 1 3 # r 列 运行队列饱和度 # 2. 内存使用率 饱和度 free -h vmstat 1 3 # si/so 恒定饱和 grep -E Dirty|Writeback /proc/meminfo # 3. 磁盘使用率 饱和度 iostat -dxm 1 3 # %util / aqu-sz # 4. 网络使用率 错误 sar -n DEV 1 3 sar -n EDEV 1 3 # 5. 全局错误 dmesg -T | tail -50USE 的排查顺序先找利用率高的、饱和的、有错误的资源。三者中任何一项异常就是线索。⚠️ USE 的盲区USE 只看物理资源。如果所有资源都正常但应用还是慢那问题在「应用层」——锁竞争、GC、慢查询、算法复杂度。这时要换 RED。三、RED 方法面向服务RED Rate请求速率、Errors错误率、Duration延迟。它从「服务/微服务」的视角看问题特别适合排查「接口慢」这类应用层问题。三个维度指标含义工具Rate每秒请求数QPS应用埋点、Nginx 日志、APMErrors每秒错误数 / 错误率应用埋点、日志Duration请求耗时分布P50/P95/P99APM、链路追踪关键Duration 要看分位数不能只看平均值。平均 50ms 的接口P99 可能是 3 秒——平均值掩盖了尾部延迟而用户体验由尾部决定。与 USE 的配合服务层异常→ 用 RED 定位是哪个服务、哪个接口。服务层正常但机器慢→ 用 USE 定位是哪个资源。两者是互补的RED 告诉你「哪里慢」USE 告诉你「为什么慢」。示例用日志算 RED# Nginx 日志里统计每分钟请求数Rate awk {print $4} access.log | cut -c14-18 | sort | uniq -c # 统计 5xx 错误率Errors awk $9 ~ /^5/ {c} END {print c} access.log # 统计耗时分布Duration需日志带 $request_time awk {print $NF} access.log | sort -n | awk {a[NR]$1} END {print P50:, a[int(NR*0.5)], P99:, a[int(NR*0.99)]}四、性能分析的通用三板斧无论用哪套方法论落地都是这三步阶段做什么关键动作观察收集现象和数据明确「慢」的定义采集指标定位缩小范围找到根因自上而下 or 自下而上逐层排除验证证明改动有效改前改后对比数据观察先定义「慢」模糊的「系统慢」没法查。要问清楚是所有操作慢还是某个接口慢从什么时候开始之前有变更吗部署、配置、流量慢到什么程度P99 多少能复现吗这一步偷懒后面全是白费。定位两种切入路线自上而下从应用/服务视角RED往下先看哪个服务慢再看资源。适合知道具体哪个接口/服务出问题。自下而上从物理资源USE往上先看哪个资源饱和再看谁用的。适合只知道「机器整体变慢」。验证用数据说话改完必须验证不能凭感觉# 改前记录基线 mpstat -P ALL 1 5 before.txt # 做优化 # 改后对比 mpstat -P ALL 1 5 after.txt diff before.txt after.txt没有验证的优化可能只是猜对了也可能是问题自己消失了。五、火焰图一把看穿 CPU 热点前面讲的是「方法」火焰图是「利器」。它把成千上万次采样数据可视化成一棵树让你一眼看出哪个函数、哪条调用链在吃 CPU。火焰图长什么样一张标准火焰图┌──────────────────────────────┐ │ main (100%) │ - 顶层入口 ├──────────────────┬───────────┤ │ process_data │ parse() │ │ (65%) │ (35%) │ ├────────┬─────────┤ │ sort() │ io() │ │ (40%) │ (25%) │ └────────┴─────────┘怎么读火焰图核心规则每一层是一个函数宽度代表它在采样中占的比例即 CPU 时间占比。越宽说明占用 CPU 越多是优化重点。从下往上是调用关系下面的函数调用了上面的函数。颜色不重要通常是随机暖色只是区分函数。看「平顶」一个宽宽的、没有明显下层的函数说明时间花在它自己身上而非它调用的子函数是热点。找最宽的、最上面那个「平坦」的方块就是元凶。六、perf 火焰图实战安装依赖sudo apt install linux-tools-common linux-tools-$(uname -r) # Ubuntu sudo dnf install perf # Rocky/CentOS火焰图需要 Brendan Gregg 的 FlameGraph 脚本git clone https://github.com/brendangregg/FlameGraph.git cd FlameGraph四步生成火焰图# 1. 采样 30 秒-g 记录调用栈-a 全系统-F 99 采样频率 99Hz sudo perf record -F 99 -a -g -- sleep 30 # 2. 导出采样数据为文本 sudo perf script out.perf # 3. 折叠调用栈 ./stackcollapse-perf.pl out.perf out.folded # 4. 生成 SVG 火焰图 ./flamegraph.pl out.folded flame.svg打开flame.svg浏览器里就能交互式查看支持点击放大、搜索函数。针对某个进程采样# 只采样 PID 1234 的进程 sudo perf record -F 99 -p 1234 -g -- sleep 30用 perf top 快速看热点来不及做完整火焰图时perf top实时看函数级热点够用sudo perf top -p 1234Overhead Symbol 42.30% [.] handle_request 18.10% [.] json_encode 9.50% [k] copy_user_generic_string⚠️ 常见坑采样频率过高-F 99是常用值调到 1000 会明显增加开销。sudo 权限perf record通常需要 root 或CAP_PERFMON。kernel.perf_event_paranoid限制设成 2 时普通用户不能采样需sudo sysctl kernel.perf_event_paranoid1。符号丢失看不到函数名全是地址说明二进制没带符号表或没装 debuginfo。Java/Python 应用默认看不到 JIT/解释器内部函数需要perf-map-agentJava或py-spyPython。七、off-CPU 火焰图抓住「不在跑」的时间标准火焰图on-CPU只展示CPU 在忙什么。但很多性能问题不是「CPU 忙」而是进程在等——等锁、等 IO、等网络。这些时间 CPU 是空闲的on-CPU 火焰图完全看不到。off-CPU 火焰图记录进程「离开 CPU」的时段和原因用来分析阻塞和延迟# 需要 eBPF/bcc 工具 sudo offcputime -df -p 1234 30 offcpu.folded ./flamegraph.pl --colorio --titleOff-CPU offcpu.folded offcpu.svg它能回答「进程为什么卡住 3 秒」——因为等某把锁或等磁盘返回。on-CPU 看热点off-CPU 看阻塞两者结合才是完整的性能画像。八、⚠️ 方法论层面的常见错误上来就测不定基线。不知道「正常」长什么样就无法判断「异常」。只修症状不找根因。重启服务、加机器能暂时缓解但根因没解决必然复发。迷信平均值。CPU 平均 30% 但单核 100%、延迟平均 50ms 但 P99 3s——平均值是最大的谎话。一次改多个变量。同时改了三处出问题不知道是哪处。一次只改一个验证后再改下一个。忽略流量模式。突增流量、定时任务备份、批处理会和业务抢资源排查时要把时间线对齐。不做压测就下结论。生产不敢压就在测试环境用wrk/jmeter/fio复现有基线才好对比。把方法论当死板流程。USE/RED 是「检查清单」不是「必须按序执行」凭线索灵活跳转。九、原理探究采样 vs 埋点火焰图为何有效采样Sampling的原理perf不记录每一次函数调用那样开销太大而是每隔固定时间触发一次中断记下此刻 CPU 正在执行哪个函数。采样几十秒得到几万个样本统计每个函数出现的频率就约等于它的 CPU 占比。采样模式的好处开销低1%~5%可以对着生产环境跑。不侵入不需要改代码、重新编译。统计有效样本足够多时频率收敛到真实的 CPU 时间占比。代价它是概率性的短命函数可能采不到。要抓偶发问题需要拉长采样时间或提高频率。为什么火焰图这么有效火焰图把「调用栈 时间占比」编码成「横轴宽度 纵向层级」利用了人眼的两个强项对宽度的直觉一眼看出哪个最宽。对层级的直觉一眼看出调用链。它把「几万行采样数据」压缩成「一张可以直接看结论的图」这就是它的威力。传统 profiler 给的是排序列表火焰图给的是结构——谁调用了谁、瓶颈在哪条路径上一目了然。从现象到根因的完整链路把整篇串起来一个成熟的性能分析流程是① 观察用 RED 确认哪个服务/接口慢用 USE 扫一遍资源 ↓ ② 缩范围排除资源饱和 → 问题在应用层 ↓ ③ 定位perf 采样 火焰图找到热点函数 ↓ ④ 深挖on-CPU 看计算热点off-CPU 看阻塞等待 ↓ ⑤ 改优化算法/加锁策略/改配置/扩资源一次一个变量 ↓ ⑥ 验证改前改后数据对比确认有效工具是「术」方法论是「道」。工具会更新换代top变htop、netstat变ss但「先观察、再定位、后验证资源用 USE、服务用 RED热点看火焰图、阻塞看 off-CPU」这套思路十年都不会过时。十、一页速查场景抓手不知道从哪查先 USE 扫资源再 RED 看服务机器整体慢自下而上USE某接口慢自上而下REDCPU 热点perf record 火焰图进程卡住off-CPU 火焰图想证明优化有效改前改后基线对比最难的一步明确定义「慢」并对齐时间线性能分析的正确姿势是先想清楚问题的定义再用方法论保证覆盖最后用采样工具定位到代码。工具会用的很多思路清醒的很少——这篇的目的就是让你成为后者。
阅读完成 · 觉得有帮助?