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响应时间
- 错误率:请求的错误比例
性能分析的通用步骤
- 先整体后局部:先看系统整体的CPU、内存、IO、网络指标,确定瓶颈大致在哪一层,再深入分析
- 从外到内:先看应用层面的指标(QPS、响应时间、错误率),再看系统层面的指标
- 对比指标:性能问题通常是相对的,要和正常情况的指标对比,才能发现异常
- 瓶颈定位顺序:通常按照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高负载排查
- 用top/htop看CPU使用率,是us高还是sy高,wa是不是很高
- wa高说明是IO瓶颈,不是CPU本身的问题
- sy高说明系统调用、内核、上下文切换消耗多
- us高说明是应用程序本身消耗CPU多
- us高的话用perf top/pprof看CPU热点函数,定位是哪个函数消耗CPU
- 上下文切换高的话用pidstat -w看是自愿切换还是非自愿切换,是不是线程太多了
2. 内存问题排查
- 用free看是不是真的内存不足,是不是buffer/cache占用太多
- Swap使用率高说明物理内存不足,需要扩容或者优化内存使用
- 用top看哪个进程占用内存多
- 内存泄漏的话,用对应语言的内存profiler工具分析,看哪里的内存没有释放
3. IO瓶颈排查
- 用iostat看磁盘%util是不是接近100%,await是不是很高
- 用pidstat -d看哪个进程占用IO多
- 用strace或者lsof看进程在读写什么文件
- 是随机IO多还是顺序IO多,是不是可以优化成顺序IO或者加缓存
4. 网络问题排查
- 用ss看连接数是不是太多,TIME_WAIT是不是太多
- 用sar -n看网络带宽是不是打满了
- 用ping/mtr看网络延迟和丢包率
- 用tcpdump/Wireshark抓包分析具体的网络请求
性能分析注意事项
- 不要过早优化:先找到瓶颈再优化,不要凭感觉盲目优化
- 测量,不要猜测:所有的优化都要有数据支撑,用工具测量瓶颈在哪里
- 对比基准线:要知道正常情况下的指标是多少,异常才有对比依据
- 生产环境小心使用工具:有些工具(比如perf、strace)会有一定的性能开销,生产环境高负载时谨慎使用
思考问题
- 系统Load高但CPU使用率不高,可能是什么原因?怎么排查?
- 磁盘%util已经100%了,但吞吐量很低,可能是什么原因?
- 排查线上服务响应变慢的问题,你的排查步骤是什么?
- 怎么区分CPU瓶颈是应用本身计算量大导致的,还是锁竞争、上下文切换导致的?