Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

10.1 系统性能分析工具

性能优化的第一步是性能分析,只有找到真正的性能瓶颈,才能针对性地优化,盲目优化只会做无用功。工欲善其事必先利其器,掌握常用的性能分析工具,能够帮助我们快速定位性能瓶颈。

性能分析的基本思路

核心性能指标

分析性能之前,我们需要先明确要关注哪些核心指标:

1. CPU相关

  • CPU使用率:用户态使用率(us)、系统态使用率(sy)、空闲率(id)、等待IO使用率(wa)
    • us高说明应用程序占用大量CPU
    • sy高说明系统调用或者内核占用大量CPU
    • wa高说明CPU在等待IO,瓶颈在磁盘或网络IO
  • 负载(Load Average):1分钟、5分钟、15分钟的平均等待运行的进程数
    • 负载大于CPU核心数说明有进程在等待CPU
    • 持续高负载说明CPU资源不足或者有阻塞的进程
  • 上下文切换次数:每秒上下文切换的次数,过高的上下文切换会消耗大量CPU资源

2. 内存相关

  • 内存使用率:已用内存/总内存,注意buffer和cache是操作系统用的缓存,不算真正的内存不足
  • 交换分区使用率(Swap usage):使用了交换分区说明物理内存不足,性能会严重下降
  • 缺页异常次数:每秒缺页异常的次数,高缺页率说明内存访问局部性差或者内存不足

3. 磁盘IO相关

  • IO使用率(util%):磁盘忙碌的时间百分比,接近100%说明磁盘IO饱和
  • IOPS:每秒IO操作次数,HDD通常100-200,SSD通常1万-10万
  • 吞吐量:每秒读写的数据量,单位MB/s
  • 平均IO等待时间(await):IO操作的平均等待时间,正常应该小于10ms,大于100ms说明IO压力大

4. 网络相关

  • 网络带宽使用率:入站/出站带宽占总带宽的比例
  • 网络连接数:TCP连接数,TIME_WAIT、ESTABLISHED状态的数量
  • 丢包率/错误率:网络数据包的丢包和错误比例,过高说明网络有问题
  • 延迟:网络请求的往返时间RTT

5. 应用相关

  • 吞吐量(QPS/TPS):每秒处理的请求数/事务数
  • 响应时间:请求的平均响应时间、P95/P99响应时间
  • 错误率:请求的错误比例

性能分析的通用步骤

  1. 先整体后局部:先看系统整体的CPU、内存、IO、网络指标,确定瓶颈大致在哪一层,再深入分析
  2. 从外到内:先看应用层面的指标(QPS、响应时间、错误率),再看系统层面的指标
  3. 对比指标:性能问题通常是相对的,要和正常情况的指标对比,才能发现异常
  4. 瓶颈定位顺序:通常按照CPU → 内存 → 磁盘IO → 网络的顺序排查

系统层面性能分析工具(Linux平台)

Linux系统有丰富的性能分析工具,最常用的有以下这些:

1. top / htop

最常用的系统监控工具,查看整体的CPU、内存、进程运行情况:

top

输出说明:

  • 第一行:系统时间、运行时间、登录用户数、1/5/15分钟负载
  • 第二行:总进程数、运行中、睡眠、停止、僵尸进程数
  • 第三行:CPU使用率:us(用户态)、sy(系统态)、ni(低优先级进程)、id(空闲)、wa(等待IO)、hi(硬中断)、si(软中断)
  • 第四行:内存使用情况:总内存、已用、空闲、缓冲、缓存
  • 第五行:交换分区使用情况
  • 下面的列表:各个进程的资源使用情况,PID、用户、CPU使用率、内存使用率、运行时间、进程名等

htop是top的增强版,界面更友好,支持鼠标操作,功能更强大,推荐优先使用。

2. vmstat

虚拟内存统计工具,查看系统整体的CPU、内存、IO、上下文切换情况:

vmstat 1  # 每秒输出一次统计信息

输出字段说明:

  • procs:r(等待运行的进程数)、b(不可中断睡眠的进程数)
  • memory:swpd(使用的交换内存)、free(空闲内存)、buff(缓冲区)、cache(页缓存)
  • swap:si(从交换分区读入的大小)、so(写入交换分区的大小),这两个值大于0说明内存不足
  • io:bi(从磁盘读入的块数)、bo(写入磁盘的块数)
  • system:in(每秒中断次数)、cs(每秒上下文切换次数),cs过高说明上下文切换太频繁
  • cpu:us、sy、id、wa、st,和top的CPU含义一样

3. iostat

磁盘IO性能分析工具,查看磁盘的使用率、IOPS、吞吐量、延迟等指标:

iostat -x 1  # 每秒输出一次扩展IO信息

输出关键字段:

  • %util:磁盘IO使用率,接近100%说明磁盘饱和
  • r/s、w/s:每秒读/写IO次数,加起来是IOPS
  • rkB/s、wkB/s:每秒读/写的KB数,加起来是吞吐量
  • await:平均每个IO的等待时间(毫秒),正常应该<10ms,>100ms说明IO压力大
  • svctm:平均IO服务时间,通常是磁盘的固有性能,HDD约8-10ms,SSD约0.1ms

4. pidstat

查看单个进程的CPU、内存、IO、线程等详细统计信息:

pidstat -u 1 -p <pid>  # 查看指定进程的CPU使用情况
pidstat -r 1 -p <pid>  # 查看指定进程的内存使用情况
pidstat -d 1 -p <pid>  # 查看指定进程的IO使用情况
pidstat -t 1 -p <pid>  # 查看进程内各个线程的资源使用情况

非常适合定位单个进程的性能瓶颈。

5. perf

Linux性能计数器工具,功能非常强大,可以分析CPU热点函数、缓存命中率、上下文切换、缺页异常等底层性能问题:

perf top  # 实时显示系统中CPU占用最高的函数,找CPU热点
perf record -g -p <pid> sleep 10  # 采样进程10秒的调用栈
perf report  # 分析perf record生成的报告,看CPU消耗在哪些函数
perf stat -p <pid>  # 统计进程的性能事件:指令数、缓存miss、分支预测miss等

perf是排查CPU性能问题的神器,可以深入到函数级别查看CPU消耗。

6. free

查看系统内存使用情况:

free -h  # 人类可读的格式显示内存使用

注意:buffer和cache是操作系统的缓存,是为了提升性能,不算应用实际占用的内存,available列是真正可用的内存大小。

7. df / du

查看磁盘空间使用情况:

df -h  # 查看各个分区的磁盘使用率
du -sh *  # 查看当前目录下各个文件/目录的大小

8. netstat / ss

查看网络连接、端口监听、网络统计信息:

ss -tunlp  # 查看所有TCP/UDP监听的端口和对应的进程
ss -s  # 查看网络连接统计信息,各个状态的连接数
netstat -i  # 查看网络接口的流量和错误统计

ss是netstat的升级版,性能更好,推荐使用。

9. sar

系统活动报告工具,可以记录和查看历史的性能数据,分析过去的性能问题:

sar -u 1  # 查看CPU使用率历史
sar -r 1  # 查看内存使用率历史
sar -n DEV 1  # 查看网络流量历史

默认会保存最近7天的性能数据,适合排查历史问题。

10. dstat

全能的系统资源统计工具,整合了vmstat、iostat、netstat等工具的功能,输出更直观:

dstat  # 同时显示CPU、磁盘、网络、分页、系统等信息

应用层面性能分析工具

1. 通用调试工具

  • gdb / lldb:C/C++程序的调试工具,可以断点调试、查看调用栈、分析core dump文件
  • strace:跟踪进程的系统调用,看进程在做什么系统调用,耗时在哪里,非常适合排查阻塞、IO相关的问题
    strace -tt -p <pid>  # 跟踪进程的所有系统调用,显示时间戳
    strace -c -p <pid>  # 统计进程的系统调用次数和耗时
    
  • ltrace:跟踪进程调用的动态库函数

2. 语言相关的Profiler

每种编程语言都有自己的性能分析工具:

  • Java:jstack(看线程栈)、jmap(堆dump)、jstat(GC统计)、VisualVM、JProfiler、Arthas(阿里开源的Java诊断工具,功能非常强大)
  • Go:pprof(内置的性能分析工具,可以分析CPU、内存、goroutine、锁竞争等)
  • Python:cProfile、line_profiler、memory_profiler、py-spy
  • C/C++:gprof、perf、Valgrind(内存问题检测)
  • Node.js:Chrome DevTools、clinic.js

3. APM(应用性能监控)系统

线上生产环境通常会部署APM系统,全链路监控应用的性能:

  • 开源APM:SkyWalking、Pinpoint、Zipkin、Jaeger
  • 商业APM:Datadog、New Relic、听云
  • 功能:
    • 全链路追踪,查看请求各个阶段的耗时
    • 接口性能监控:QPS、响应时间、错误率
    • 数据库、缓存、外部调用的性能监控
    • JVM、进程资源监控
    • 异常和错误告警

APM系统是排查线上性能问题的首选工具,可以快速定位慢请求、瓶颈点。

4. 前端性能分析工具

  • 浏览器开发者工具:Network面板看网络请求性能,Performance面板看页面加载和运行时性能
  • Lighthouse:谷歌开源的网页性能分析工具,给出性能评分和优化建议
  • Web Vitals:谷歌定义的核心网页性能指标:LCP(最大内容绘制)、FID(首次输入延迟)、CLS(累积布局偏移)

性能瓶颈定位实战

常见瓶颈的定位思路

1. CPU高负载排查

  1. 用top/htop看CPU使用率,是us高还是sy高,wa是不是很高
    • wa高说明是IO瓶颈,不是CPU本身的问题
    • sy高说明系统调用、内核、上下文切换消耗多
    • us高说明是应用程序本身消耗CPU多
  2. us高的话用perf top/pprof看CPU热点函数,定位是哪个函数消耗CPU
  3. 上下文切换高的话用pidstat -w看是自愿切换还是非自愿切换,是不是线程太多了

2. 内存问题排查

  1. 用free看是不是真的内存不足,是不是buffer/cache占用太多
  2. Swap使用率高说明物理内存不足,需要扩容或者优化内存使用
  3. 用top看哪个进程占用内存多
  4. 内存泄漏的话,用对应语言的内存profiler工具分析,看哪里的内存没有释放

3. IO瓶颈排查

  1. 用iostat看磁盘%util是不是接近100%,await是不是很高
  2. 用pidstat -d看哪个进程占用IO多
  3. 用strace或者lsof看进程在读写什么文件
  4. 是随机IO多还是顺序IO多,是不是可以优化成顺序IO或者加缓存

4. 网络问题排查

  1. 用ss看连接数是不是太多,TIME_WAIT是不是太多
  2. 用sar -n看网络带宽是不是打满了
  3. 用ping/mtr看网络延迟和丢包率
  4. 用tcpdump/Wireshark抓包分析具体的网络请求

性能分析注意事项

  1. 不要过早优化:先找到瓶颈再优化,不要凭感觉盲目优化
  2. 测量,不要猜测:所有的优化都要有数据支撑,用工具测量瓶颈在哪里
  3. 对比基准线:要知道正常情况下的指标是多少,异常才有对比依据
  4. 生产环境小心使用工具:有些工具(比如perf、strace)会有一定的性能开销,生产环境高负载时谨慎使用

思考问题

  1. 系统Load高但CPU使用率不高,可能是什么原因?怎么排查?
  2. 磁盘%util已经100%了,但吞吐量很低,可能是什么原因?
  3. 排查线上服务响应变慢的问题,你的排查步骤是什么?
  4. 怎么区分CPU瓶颈是应用本身计算量大导致的,还是锁竞争、上下文切换导致的?