一、性能剖析概述

什么是性能剖析

性能剖析,说白了就是给程序做「体检」。

你写了一段代码,跑起来了,功能也对了。但你真的知道它跑得怎么样吗?

我刚开始做开发那会儿,总觉得「能跑就行」。直到有一次线上服务突然卡死,查了半天才发现是一个循环里做了大量字符串拼接。嗯,从那以后,我就养成了定期做性能剖析的习惯。

性能剖析的核心,就是回答三个问题:

  • 慢在哪 —— 哪个函数、哪行代码耗时最长
  • 吃多少 —— CPU、内存、IO、网络分别用了多少
  • 为什么 —— 是算法问题?还是资源争抢?

你可以把它想象成医生用的听诊器。没有它,你只能靠猜。有了它,你就能精准定位病灶。

为什么需要性能剖析

你可能会问:「我代码写得挺规整的,有必要吗?」

我个人经验是:有必要,而且非常有必要。

举个例子。我曾经接手过一个数据处理系统,每天跑批要花6个小时。业务方天天催,开发团队也改了好几次,效果都不明显。后来我用性能剖析工具一查,发现80%的时间都花在了一个数据库查询上——索引没建对。改完之后,跑批时间直接降到40分钟。

你看,没有数据支撑的优化,就是瞎优化。

性能剖析能帮你做到三件事:

  1. 量化问题 —— 不说「有点慢」,而是说「这个接口平均耗时2.3秒」
  2. 定位根因 —— 不说「可能是数据库的问题」,而是说「这条SQL全表扫描了100万行」
  3. 验证效果 —— 优化前测一次,优化后测一次,数据说话

核心观点:没有性能剖析的优化,等于蒙着眼睛修车。

性能剖析的核心指标

做性能剖析,你得知道看什么指标。我一般关注四个维度:CPU、内存、IO、网络。这四样,缺一不可。

1. CPU

CPU指标反映的是「计算密集度」。说白了,就是你的程序在多大程度上「烧」CPU。

关键指标包括:

指标 说明 警戒线
CPU使用率 CPU被占用的百分比 持续 > 80% 需关注
用户态/内核态占比 区分是业务代码还是系统调用消耗的CPU 内核态 > 30% 可能有系统调用瓶颈
上下文切换次数 线程切换的频率 每秒 > 10万次需排查
平均负载 正在运行+等待运行的进程数 超过CPU核数说明有排队

我记得有一次排查一个Java服务,CPU使用率一直飙在95%以上。用top一看,发现是GC线程在疯狂跑。再深入一看,堆内存设置太小,对象频繁晋升到老年代,触发Full GC。调大堆内存后,CPU直接降到20%。

小技巧:排查CPU问题时,先用top看整体,再用perf top或火焰图定位热点函数。

2. 内存

内存指标关注的是「空间使用效率」。内存泄漏、频繁GC、大对象分配,都是常见问题。

关键指标:

指标 说明 警戒线
内存使用率 已用内存占总内存的比例 持续 > 85% 需关注
GC频率和停顿时间 垃圾回收的频次和耗时 Full GC > 1次/分钟 或停顿 > 1秒
堆内/堆外内存 Java中区分JVM堆和直接内存 堆外内存增长异常需排查
内存泄漏增长率 内存使用是否随时间持续增长 每次GC后内存不回落,大概率泄漏

我曾经遇到过一个诡异的问题:服务运行两天后就会OOM。用jmap dump了堆快照,发现一个HashMap里存了上千万个对象,而且只增不减。查代码发现是缓存没设过期策略。嗯,这种坑踩过一次就记住了。

注意:内存泄漏往往不是一下子爆出来的,而是慢慢「温水煮青蛙」。建议对内存使用做持续监控,而不是出问题了才看。

3. IO

IO指标关注的是「数据读写效率」。磁盘IO慢,往往是整个系统的瓶颈。

关键指标:

指标 说明 警戒线
IOPS 每秒读写次数 接近磁盘上限需关注
吞吐量 每秒读写的数据量 接近带宽上限需关注
IO等待时间 进程等待IO完成的时间 %iowait > 30% 说明磁盘是瓶颈
IO队列长度 等待处理的IO请求数 队列持续 > 磁盘并发数

你想想看,CPU处理一个指令是纳秒级的,磁盘寻道却是毫秒级的。差了上百万倍。所以IO优化往往是性价比最高的优化方向。

4. 网络

网络指标关注的是「数据传输效率」。微服务架构下,网络问题尤其常见。

关键指标:

指标 说明 警戒线
带宽使用率 已用带宽占总带宽的比例 持续 > 70% 需关注
延迟 请求从发出到收到响应的时间 P99 > 500ms 需排查
丢包率 丢失的数据包占比 丢包率 > 0.1% 说明网络不稳定
连接数 当前建立的TCP连接数 接近系统上限需关注

我记得有一次排查一个接口超时问题,代码层面怎么看都没毛病。后来用tcpdump抓包一看,发现每次请求都要做三次握手——原来是连接池没配好,每次请求都新建连接。改成连接复用后,延迟从800ms降到了50ms。

四个指标的关系

这四个指标不是孤立的。它们之间会相互影响:

  • CPU高,可能是因为内存不足导致频繁GC
  • IO慢,会导致CPU大量时间花在等待上
  • 网络延迟高,会让线程长时间阻塞,间接增加上下文切换

所以做性能剖析时,我建议你四个维度一起看,不要只盯着一个。

性能剖析 CPU 内存 IO 网络 使用率 · 上下文切换 用户态/内核态 · 平均负载 使用率 · GC频率 · 停顿 堆内/堆外 · 泄漏增长率 IOPS · 吞吐量 IO等待 · 队列长度 带宽 · 延迟 · 丢包率 · 连接数 四大核心指标相互影响,需综合分析

总结一下:性能剖析就是给程序做体检。四个核心指标——CPU、内存、IO、网络——就像体检报告上的四项关键数据。哪个指标异常,就说明哪个环节有问题。我建议你把这四个指标刻在脑子里,每次排查问题都过一遍。

我的习惯:接到性能问题,先看CPU和内存,再看IO和网络。因为前两个最容易暴露问题,后两个往往需要更深入的排查手段。当然,具体问题具体分析,没有固定的顺序。

好了,这一章就聊到这儿。下一章我们开始动手,看看怎么用具体的工具来采集这些指标数据。

可可精品资料库