前言
本文主要内容来自: Gregg B. BPF Performance Tools[M]. Addison-Wesley Professional, 2019. BPF之巅(洞悉Linux系统和应用性能)(上述译本) 加了部分自己的理解和补充,作为一个Linux性能分析笔记。
从目标谈起——为什么要进行性能分析
在进行性能分析之前,不妨先思考一下,性能分析的目标是什么?
一般来说,性能分析的目标是为了改进用户体验、降低运行成本,或者单纯为了检验测试和学术目的,对某个指标进行测试分析。
为了进行测试分析,我们就需要对分析的目标进行量化,如:
我理解,量化分析的指标必须对我们一开始的目标有用,否则分析工作没有了上下文,很容易跑偏。
方法论
这里学习一下Brendan Gregg前辈的几种方法论,虽然有些方法论现在并不是很理解,希望以后能体会到吧。
业务负载画像
即通过对实际的业务负载进行几个方面的测试,得到业务负载实际的“画像”。
可以遵循这样一些步骤:
- 负载是谁产生的?(如进程ID、用户ID、进程名、IP地址……)
- 负载为何会产生? (代码路径、调用栈、火焰图……)
- 负载的组成如何?(IOPS、吞吐量、负载类型……)
- 负载随着时间会发生何种变化?(周期信息……)
通过总体的业务负载画像,去找到问题所在。
下钻分析
下钻分析即从某一个指标开始,进一步拆分和定位更深的线索,直到找出一个或多个根本原因。
可以遵循以下步骤:
- 从业务最高层级开始分析;
- 检查下一层级的细节;
- 挑出最有可能的部分或线索分析;
- 如果问题仍未解决,跳到第2步;
USE方法论
全称Utilization Saturation and Errors Method,即针对每一个资源,依次检查:
- 使用率
- 饱和度
- 错误
检查清单法
列出一系列工具和指标,用于对照运行和检查,说起来感觉这才是实际使用时最常用的方法。
Linux 快速分析
下面的清单适用于任何性能问题的分析工作。
先给出清单:
工具 | 功能简述 |
---|
uptime | 检查Linux系统负载 | dmesg | tail | 显示系统日志(过去10条) | vmstat | 显示系统的CPU使用率、内存使用、虚拟内存交换、IO读写情况 | mpstat -P ALL 1 | 打印每个CPU各个状态下的CPU时间占比 | pidstat 1 | 滚动打印每个进程展示CPU的使用情况 | iostat -xz 1 | 显示存储设备的I/O指标 | free -m | 查看内存及虚拟内存使用情况 | sar -n DEV 1 | 查看网络设备指标 | sar -n TCP,ETCP 1 | 查看TCP指标和错误信息 | top | 提供对系统的实时状态监视 |
1. uptime
uptime命令十分简单,用于快速检查Linux系统的平均负载。
如下输出分别显示了:
当前时间、系统已运行时间、用户数量、系统在过去的 1 分钟、5 分钟和 15 分钟内的平均负载。
平均负载是指单位时间内系统的平均进程数(包括可运行状态和不可中断状态的进程),和CPU使用率并没有直接关系。
可运行状态的进程是指正在使用或等待CPU的进程,是可以用ps命令看到的、处于R状态(Running或Runnable)的进程;
不可中断状态的进程是指正处于内核态关键流程中的进程,这些流程是不可打断的,如一个进程向磁盘读写数据时,在得到磁盘回复前,它是不能被其他进程或中断打断的,这时的进程就处于不可中断状态。
需要注意的是uptime显示的平均负载是所有CPU核心的总体平均负载,需要考虑到CPU数和CPU核心数,负载平均到每个核需要除以系统CPU核数。
网上找到了一些经验参考值,也不知道是否靠谱:首先平均到每核的平均负载最好是不要超过1,负载临界点在3~5,高于这个临界点就认为负载过高,需要进行优化调整了。
$ uptime
01:34:51 up 9 min, 1 user, load average: 0.61, 1.05, 0.65
此外如果在寻找性能问题时,发现平均负载同时存在过去15分钟的高负载和过去1分钟的低负载,说明已经错过了问题发生的现场。
还发现Linux下一个很好用的工具:
watch -d [命令]
可以实时显示命令执行结果,并高亮显示变化的区域。
2. dmesg | tail
dmesg用于显示系统日志,tail用以查看最近10条日志。这里可能会找到引起性能问题的错误,甚至引导下一步的分析方向。
$ dmesg | tail
[1880957.563150] perl invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[...]
[1880957.563400] Out of memory: Kill process 18694 (perl) score 246 or sacrifice child
[1880957.563408] Killed process 18694 (perl) total-vm:1972392kB, anon-rss:1953348kB, file-rss:0kB
[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request. Check SNMP counters.
比如上述dmesg信息显示了内存不足和TCP丢弃请求的记录,TCP的相关日志也指引了分析方向:查看SNMP计数值。
3. vmstat 1
vmstat指virtual memory status,该命令每隔一秒显示当前系统的CPU使用率、内存使用、虚拟内存交换、IO读写情况。
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 26748 4278632 54748 1596880 0 1 114 250 333 548 4 2 94 0 0
3 0 26748 4278244 54748 1596880 0 0 0 0 1561 1708 50 3 48 0 0
3 0 26748 4278244 54748 1596880 0 0 0 0 1897 2193 49 3 48 0 0
2 0 26748 4278244 54748 1596880 0 0 0 0 1782 2024 50 1 48 0 0
2 0 26748 4278244 54756 1596872 0 0 0 12 1621 1736 50 1 49 0 0
2 0 26748 4278244 54756 1596880 0 0 0 0 2208 2656 50 3 48 0 0
标头和数据没有完全对齐很让人难受
注意第一行输出的是自系统启动后的统计值(内存相关的计数器除外)。
依次介绍:
我们就主要关注以上加粗部分吧。
4. mpstat -P ALL 1
将每个CPU各个状态下的CPU时间占比打印出来。比如某个CPU用户态占比过高是单个线程遇到瓶颈的特征;%iowait过高需要使用磁盘I/O工具进一步分析……
$ mpstat -P ALL 1
[...]
05:29:59 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
05:30:00 AM all 25.19 0.00 0.25 0.00 0.00 1.23 0.00 0.00 0.00 73.33
05:30:00 AM 0 0.97 0.00 0.00 0.00 0.00 2.91 0.00 0.00 0.00 96.12
05:30:00 AM 1 1.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00
05:30:00 AM 2 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
05:30:00 AM 3 0.98 0.00 0.00 0.00 0.00 1.96 0.00 0.00 0.00 97.06
5. pidstat 1
按每个进程展示CPU的使用情况,相比top来讲可以滚动打印,这样可以采集到不同时间段的数据变化。
$ pidstat 1
05:34:11 AM UID PID %usr %system %guest %wait %CPU CPU Command
05:34:12 AM 0 1 0.00 1.00 0.00 0.00 1.00 1 systemd
05:34:12 AM 1000 1693 1.00 1.00 0.00 0.00 2.00 0 Xorg
05:34:12 AM 1000 1815 1.00 1.00 0.00 0.00 2.00 0 gnome-shell
05:34:12 AM 1000 2152 0.00 1.00 0.00 0.00 1.00 0 gnome-terminal-
05:34:12 AM 0 2733 1.00 0.00 0.00 0.00 1.00 0 supervisord
05:34:12 AM 0 2919 1.00 6.00 0.00 0.00 7.00 1 ovsdb-server
05:34:12 AM 0 2948 0.00 1.00 0.00 0.00 1.00 0 controller_vtep
05:34:12 AM 0 3328 2.00 0.00 0.00 0.00 2.00 1 frrconfig_main
05:34:12 AM 1000 37123 100.00 0.00 0.00 0.00 100.00 3 stress
05:34:12 AM 1000 37124 100.00 0.00 0.00 0.00 100.00 2 stress
6. iostat -xz 1
显示存储设备的I/O指标。
不全列了,我们列几个需要检查的:
- r/s、w/s、rkB/s、wkB/s分别是每秒向设备发送的读、写次数及字节数。
- r_await、w_await:I/O读写的平均响应时间(毫秒)。这是应用需要承受的时间,同时包含了I/O队列时间和服务时间。若大于预期的平均响应时间,可看作设备已饱和或设备层面有问题的表征。
- aqu-sz:设备请求队列的平均长度。比1大则有可能是设备已饱和(但对于有些设备,尤其是基于多块磁盘的虚拟设备,通常以并行方式处理请求,值也可能大于1)。
- %uil:设备使用率,代表设备繁忙程度,大于60%的值可能会导致性能变差(await时间变长),但也取决于具体设备。接近100%的值通常代表设备已饱和。
7. free -m
以MB为单位显示系统内存和虚拟内存使用情况。
$ free -mw
total used free shared buffers cache available
Mem: 8003 2892 117 32 79 4913 4791
Swap: 2047 27 2020
8. sar -n DEV 1
sar工具用处就多了,这里的命令是查看网络设备指标,通过接口吞吐量看是否有设备达到了能力上限。
$ sar -n DEV 1
Average: IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
Average: lo 1008.98 1008.98 82.58 82.58 0.00 0.00 0.00 0.00
Average: eth1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: eth3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: eth4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: eth2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: eth0 4563.20 4563.18 267.38 267.38 0.00 0.00 0.00 0.22
9. sar -n TCP,ETCP 1
查看TCP指标和TCP错误信息,其中:
- active/s:每秒本地发起的TCP连接数量(通过调用connect()创建);
- passive/s:每秒远端发起的TCP连接数量(通过调用accept()创建);
- retrans/s:每秒TCP重传的数量。
$ sar -n TCP,ETCP 1
Average: active/s passive/s iseg/s oseg/s
Average: 6.00 0.00 31.00 30.00
Average: atmptf/s estres/s retrans/s isegerr/s orsts/s
Average: 6.00 0.00 0.00 0.00 6.00
主动和被动连接计数对于业务负载画像很有用。重传则是网络或远端主机有问题的征兆。
10. top
用的最广泛的,包含多种信息,实时变动实时监控,可以对一些信息做进一步的确认。
小结
至此,一些性能问题的线索可能已经有了,接下来可以使用其他工具或BPF开展进一步的分析,BPF的性能分析目前把Brendan Gregg的《BPF Performance Tools》作为字典参考,对于洞悉Linux系统和应用性能有很大帮助。
参考
大量参考于: Gregg B. BPF Performance Tools[M]. Addison-Wesley Professional, 2019. BPF之巅(洞悉Linux系统和应用性能)(上述译本)
|