性能指标与度量:CPU、内存、磁盘、网络、吞吐量、延迟

性能调优这件事,说白了就是跟数字打交道。我刚入行的时候,总觉得调优就是凭感觉改参数,结果经常把系统改崩了。后来才明白——没有度量,就没有优化。你连瓶颈在哪都不知道,怎么下手?

这节课我们就把性能调优最核心的几类指标过一遍。CPU、内存、磁盘、网络,再加上吞吐量和延迟这两个综合指标。我保证,搞懂这些,你再看系统性能问题,心里就有底了。

先记住一个原则:指标不是孤立的。CPU 高可能是内存不够导致频繁GC,磁盘 I/O 慢可能是网络带宽抢了CPU时间片。后面我会用具体案例说明。

CPU 指标:算力到底够不够?

CPU 是系统的发动机。我见过太多人一看到 CPU 100% 就慌了,其实不一定有问题——如果你跑的是 CPU 密集型的计算任务,100% 反而是好事,说明资源用满了。真正该警惕的是CPU 满载但吞吐量上不去,那说明有锁竞争或者上下文切换过多。

关键指标就这几个:

  • %user:用户态CPU占用高?说明应用在干活,合理。
  • %sys:内核态CPU占用高?小心系统调用频繁,可能是I/O或锁问题。
  • %iowait:CPU在等磁盘/网络?这是性能瓶颈的常见信号。
  • %idle:空闲太多?资源可能没喂饱,或者架构有瓶颈。
  • 上下文切换次数 (cswch/s):这个值如果大于10万/秒,通常意味着线程数过多或锁粒度太细。

我在项目中遇到过一个问题:一个 Java 服务 CPU 一直在 90% 左右,但每秒请求数只有几百。top 一看,%sys 占了 30%。再用 strace 跟一下,发现是日志框架每写一条日志就做一次文件锁。换成异步日志后,CPU 降到 40%,吞吐量翻了 3 倍。

# 用 top 看 CPU 分解
top -bn1 | grep "Cpu(s)"
# 结果类似:
# %Cpu(s):  45.2 us,  12.8 sy,  0.0 ni, 38.7 id,  3.3 wa,  0.0 hi,  0.0 si,  0.0 st

# 用 vmstat 看上下文切换
vmstat 1 3
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
#  3  0      0 2048000   5000 200000    0    0    10    20 1000 80000 45 13 39  3  0
曾经有个坑:我在给一个Nginx反向代理做调优时,发现%wa高但磁盘I/O很低。查了半天才发现是网络驱动中断把CPU拖垮了。所以%iowait不一定只代表磁盘,也可能是网卡。

内存指标:你的应用到底吃了多少?

内存调优的核心不是看还剩多少,而是看谁在用、怎么用的。我习惯先用 free -m 看个大概,再用 /proc/meminfo 细看。当然,对于 Java 应用,还得上 jmap/jstat 看堆内存。

指标 含义 警戒值
MemTotal 物理内存总量 —
MemFree 空闲物理内存 低于10%时注意
Buffers / Cached 系统缓存(包括磁盘缓存、inode缓存等) 不必担心,系统会自动释放
SwapUsed 用了多少交换分区 大于0就说明物理内存不够用了
Page Faults (majflt) 主缺页中断(需要从磁盘读数据到内存) 持续>100次/秒就是瓶颈

我遇到过一个经典案例:一个 Redis 缓存集群,明明有 64G 内存,用 top 看到可用内存还剩 40G,但响应越来越慢。我说不对,肯定有什么猫腻。查了 /proc/meminfo,发现 Slab 占了 20G——原来是内核的 dentry cache(目录项缓存)炸了。文件数量太多,dentry 缓存一直在增长,导致内存碎片化。最后调了 vm.vfs_cache_pressure=200 才解决。

# 查看 Slab 内存占用
cat /proc/meminfo | grep -E "Slab|SReclaimable|SUnreclaim"

# 调整 dentry 缓存回收压力
sysctl -w vm.vfs_cache_pressure=200
一个技巧:如果你看到 MemFree 很少但 Buffers/Cached 很大,别急。Linux 会尽量使用空闲内存做缓存,这是好事。真正要关注的是 SwapUsed——一旦开始换页,性能就要崩。

磁盘 I/O 指标:系统到底在读写什么?

磁盘往往是最大的瓶颈,尤其是机械盘。现在 SSD 好一些,但 I/O 延迟依然是关键。我个人习惯用 iostat -x 1 盯几个核心指标:

  • r/s + w/s:每秒读写请求数。单个机械盘一般能到 200~300,SSD 能到 10万+。
  • rkB/s + wkB/s:吞吐量。结合队列深度看。
  • await:平均每次 I/O 的等待时间(包含排队+服务)。机械盘一般 5~10ms,SSD 在 0.1~1ms。超过 20ms 就慢得离谱了。
  • %util:磁盘繁忙百分比。100% 说明完全饱和,但不一定就是瓶颈——队列深度也很重要。
  • svctm:实际服务时间(不包括排队)。如果 svctm 接近 await,说明排队少,瓶颈在磁盘本身;如果 await 远大于 svctm,说明排队严重。

我曾经优化过一个日志收集系统。写日志的日志盘 %util 才 30%,但 await 已经 50ms 了。一看 svctm,才 2ms。说明磁盘服务能力足够,但请求排队太长——因为日志进程用了同步写,每个请求都在等 fsync。换成批量写+异步 fsync,await 降到 5ms,吞吐提高了 5 倍。

# 用 iostat 看磁盘延迟
iostat -x 1 3
# 输出示例(关键列):
# Device:  rrqm/s  wrqm/s r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz await svctm %util
# sda       0.00    10.00  100.00 200.00  500.00  1000.00 10.00    2.50   8.33 2.00 60.00
避坑指南:云厂商提供的 EBS(弹性块存储)经常有突发带宽,但用完突发额度后性能会骤降。我曾经遇到过云盘 %util 才 20% 但 iowait 很高的情况,查了云控制台发现是 IOPS 配额用完了。所以一定要结合云平台的监控一起看。

网络指标:带宽延迟与丢包

网络调优很容易被忽视。我记得有一次线上告警,用户反馈下单很慢,但后端服务器负载都很低。查了网络才发现,延迟高达 500ms——原来是内网交换机的一个端口协商到了百兆(正常应该千兆)。

网络指标分两大类:

  1. 延迟类:ping 测网络延迟,TCP 连接建立时间(通过 tcpdump 分析握手包),服务端处理时间(应用日志记录)。
  2. 吞吐量类:带宽使用率(iftop/nethogs 看),每秒数据包数(pps),丢包率(netstat -i 里的 dropped 列)。

我常用这些命令:

# 看网卡整体统计
netstat -i
# Kernel Interface table
# Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
# eth0  1500 12345678 0 12 0 9876543 0 4 0 BMRU

# 看实时带宽
iftop -i eth0 -n -P

# 看 TCP 连接状态
ss -tan | awk '{print $1}' | sort | uniq -c
# 输出示例:
#     10 ESTAB
#      3 TIME-WAIT
#      2 CLOSE-WAIT

这里有个点要注意:TIME-WAIT 太多不一定是坏事,它只是表示连接正常关闭后的等待状态。但 CLOSE-WAIT 太多就危险了,说明应用没有正确关闭连接。我曾经调过一个 Web 服务,CLOSE-WAIT 堆积到几万个,最后后端连接池用尽。排查后发现是 HTTP 客户端没有设置超时,修复后一切正常。

综合指标:吞吐量与延迟

吞吐量(Throughput)和延迟(Latency)是性能优化的终极目标。这两个指标通常是跷跷板关系——你想提高吞吐,往往就要容忍更长的排队延迟;你想降低延迟,可能就要牺牲吞吐。

我习惯用队列模型来理解:

  • 吞吐量 = 处理速率 × 并行度
  • 延迟 = 服务时间 + 排队时间

现实中,你应该关注尾延迟(比如 P99 延迟),而不是平均值。因为 99% 的请求如果都很快,但 1% 的请求慢到超时,用户体验依然很差。我在电商大促时调过 Redis 缓存,平均延迟 2ms,但 P99 延迟达到了 200ms。后来发现是热 Key 导致单节点过载,用本地缓存分流后才降到 5ms。

我曾经犯过的错:只看平均延迟,以为系统很健康。结果压测时一跑,P99 从 5ms 飙到 5s,但平均延迟才 50ms。从那以后,我每次做性能测试都会把百分位延迟打出来。

一张图看懂指标关系

下面我画了一张关系图,帮你理清这些指标是怎么串起来的。你可以把它当作调优的思维框架。

性能指标关系图:从资源到体验 用户请求 吞吐量(Throughput) 延迟(Latency) CPU 利用率 内存使用 磁盘 I/O 网络带宽 上下文切换 %user / %sys %iowait 运行队列长度 MemFree / Swap 缺页中断 堆使用 / GC Slab 缓存 r/s / w/s await / svctm %util 队列深度 带宽 / 延迟 丢包率 / 重传 TCP 状态分布 PPS ▲ 顶层决定体验,底层反映资源;调优时自底向上排查,自顶向下设定目标。

从这张图你可以看出:用户请求进来,先看吞吐量和延迟是否达标。如果不达标,就往下一层看——是CPU满了?内存不够了?磁盘卡住了?还是网络带宽瓶颈?逐层排查,才能找到真凶。

一个小结

你想想看,性能调优就像医生看病。CPU、内存、磁盘、网络就是四大生命体征,吞吐量和延迟就是你感受到的症状。没有指标,你连病人的体温都不知道,怎么开药?

我个人习惯在服务启动时就收集好这些指标,做成监控大盘。不要等出问题了再临时抱佛脚。下一节我们会讲具体的监控工具和可视化方法,但那之前,你得先把这些指标的含义刻在脑子里。

嗯,这章内容不少,但都是干货。你先消化一下,有什么问题欢迎在评论区留言。我当年啃这些指标的时候也花了很长时间,别急,一步步来。