一张源自USE法的Linux检查清单表。用来检查系统健康状态,发现常见资源瓶颈和错误的方法。性能工具常有改进并不断有新工具问世,因此你应当把这些工具当作需要更新的起点。同样,也可以开发出新的观测框架和工具,使得使用USE法更加容易。
物理资源
模块 | 类型 | 指标 |
---|---|---|
CPU | 利用率 | 每个CPU:mpstat -P ALL ,(取剩下部分)%idle; sar -P ALL ,%idle系统范围: vmstat 1 ,id项; sar -u ,%idle项; dstat -c ,idl项每个进程: top ,%CPU项;htop ,%CPU项;ps -o pcpu ;pidstat 1 ,%CPU项每个内核线程: top/htop (按K转换显示),找到VIRT==0(启发式) |
CPU | 饱和度 | 系统范围:vmstat 1 ,r > CPU数量[^1];sar -q ,runq-sz > CPU数量;dstat -p ,run > CPU数量每个进程: /proc/PID/shedstat 第二项(sched_info.run_delay);getdelays.c,CPU[^2];perf sched latency(显示每次调试的平均和最大的延时);动态跟踪,例如SystemTap中schedtimes.stp.queued(us)[^3] |
CPU | 错误 | 如果处理器特定错误事件(CPC)可用,使用perf(LPE) ;例如,AMD64的"04Ah Single-bit ECC Errors Recorded by Scrubber"[^4] |
内存容量 | 利用率 | 系统范围:free -m ,Mem:(主存),Swap:(虚存);vmstat 1,free项(主存),swap项(虚存);sar -r ,%memused项;dstat -m ,free项;slabtop -s c 检查 kmem slab 使用情况 每个进程:top/htop,RES项(驻留主存),VIRT项(虚存),Mem项为系统范围内的总计 |
内存容量 | 饱和度 | 系统范围:vmstat 1 ,si/so项(交换);sar -B ,pgscank项+pgscand项(扫描);sar -W 每个进程:getdelays.c,SWAP项[^2];/proc/PID/stat中第10项(min_flt)可以得到将要缺页率,或者使用动态跟踪[^5]; dmesg | grep killed (OOM进程终结者) |
内存容量 | 错误 | dmesg 可以得到物理失效;动态跟踪,例如,使用uprobes获得失败的malloc()数量(DTrace/SystemTap) |
网络接口 | 利用率 | ip -s link ,RX/TX 吞吐量除以最大带宽;sar -n DEV 项,rx/tx kB/s 除以最大带宽;/proc/net/dev ,RX/TX 吞吐量字节数除以最大值 |
网络接口 | 饱和度 | ifconfig ,overruns项,dropped项[^6]; netstat -s ,重新传输段数;sar -n EDEV 项,*drop/s项,*fifo/s项;/proc/net/dev ,RX/TX 丢包;动态跟踪其他 TCP/IP 栈排除情况 |
网络接口 | 错误 | ifconfig ,errors项,dropped项[^6]; netstat -i ,RX-ERR/TX-ERR;ip -s link ,errors项,sar -n EDEV 所有项;/proc/net/dev ,errs,drop;其他计数器可能可以在 /sys/class/net/... 下找到;动态跟踪驱动函数的返回值 |
存储设备I/O | 利用率 | 系统范围:iostat -xz 1 ,%util;sar -d %util;每个进程: iotop ;/proc/PID/sched se.statistics.iowait_sum |
存储设备I/O | 饱和度 | iostat -xnz 1 ,avgqu-sz > 1,或者较高的await;sar -d 的相同项;LPE块探针以获取队列长度/延时;动态/静态跟踪 I/O 子系统(包括LPE块探针) |
存储设备I/O | 错误 | /sys/devices/.../ioerr_cnt;smartctl ;动态/静态跟踪 I/O 子系统响应代码[^7] |
存储容量 | 使用率 | swap: swapon -s ;free; /proc/meminfo SwapFree/SwapTotal;文件系统:df -h |
存储容量 | 饱和度 | 不太确定这项是否有意义——一旦满会返回ENOSPC |
存储容量 | 文件系统:错误 | strace 跟踪 ENOSPC;动态跟踪 ENOSPC;/var/log/messages errs,取决于文件系统;应用程序日志错误 |
存储控制器 | 使用率 | iostat -xz 1 ,把设备的数值加起来与已知的每张卡 IOPS/吞吐量进行对比 |
存储控制器 | 饱和度/错误 | 参见存储设备 I/O 饱和度和错误 |
网络控制器 | 使用率 | 从ip -s link(或者 sar,或者 /proc/net/dev)和已知控制器的最大吞吐量推断出接口类型 |
网络控制器 | 饱和率/错误 | 参见网络接口饱和度和错误 |
CPU互联 | 使用率 | LPE(CPC)获得 CPU 互联端口,用吞吐量除以最大值 |
CPU互联 | 饱和度 | LPE(CPC)获得停滞周期 |
CPU互联 | 错误 | LPE(CPC)得到的所有信息 |
内存互联 | 使用率 | LPE(CPC)获得内存总线,用吞吐量除以最大值;或者大于 10 的 CPI;CPC 可能有本地和远程计数器的对比 |
I/O互联 | 使用率 | LPE(CPC)获得吞吐量除以最大值(如果能够获得);通过 iostat/ip/... 获得的已知吞吐量进行推断 |
内存& I/O互联 | 饱和度 | LPE (CPC)获得停滞周期 |
内存& I/O互联 | 错误 | LPE(CPC)得到的所有信息 |
列 r 报告了那些正在等待以及正在 CPU 上运行的线程。参见第 6 章中关于
vmstat(1)
的描述。使用延时核算,参见第 4 章。
还有一个为
perf(1)
服务的跟踪点 sched:sched_process_wait;由于调试事件很频繁,跟踪时注意额外的开销。在最新的 Intel 和 AMD 处理器手册中没有很多错误相关的事件。
可以通过查看谁造成了次要缺页,来展示谁正在消耗内存并导致饱和。在
htop(1)
中应该可以通过 MINFLT 一项得到。丢弃的报文被包含在了饱和度和错误的指标内,因为饱和及错误都有可能造成报文的丢弃。
这包括了跟踪 I/O 子系统中不同层次的函数:块设备、SCSI、SATA、IDE......有些静态探针可用(LPEscsi 和 block跟踪事件),否则就使用动态跟踪。
一般说明:上面并未包含 uptime 命令的 load average 项,原因是 Linux 的负载均衡包括了处于无法中断状态的 I/O 任务。
LPE
:Linux 性能事件(Linux Performance Events)是一个强大的观测工具,它读取 CPC 并且可以使用动态和静态跟踪技术。它的接口即 perf(1) 命令。它在第6章有介绍。CPC
:CPU 性能计数器(CPU performance counter)。参见第 6 章,用法参考 perf(1)。I/O互联
:包括了 CPU 到 I/O 的控制器总线、I/O 控制器,以及设备总线(例如PCIe)。动态跟踪
:可以开发自定义的指标。参见第 4 章以及后面几章内的例子。Linux 上的动态跟踪工具包括了LPE、DTrace、SystemTap 和 LTTng。对于任何资源施加限制的环境(例如云计算),对每一种资源控制采用USE法。这些资源控制和资源限制有可能在物理资源完全耗尽之前就被触发。
软件资源
模块 | 类型 | 指标 |
---|---|---|
内核态互斥量 | 使用率 | 内核编译带 CONFIG_LOCK_STAT=y 的情况下,使用 /proc/lock_stat 里的 holdtime-total 项除以 acquisitions 项(另外参考 holdtime-min、holdtime-max)[^1];对锁函数或者指令(可能有)进行动态跟踪 |
内核态互斥量 | 饱和度 | 内核编译带 CONFIG_LOCK_STAT=y 的情况下,使用 /proc/lock_stat 里的 waittime-total 项除以 contentions 项(另外参考waittime-min、waittime-max);对锁函数或者指令(可能有)进行动态跟踪;旋转情况也可以通过剖析显示出来(perf record -a -g -F 997... 、oprofile、DTrace、SystemTap) |
内核态互斥量 | 错误 | 动态跟踪(例如递归进入互斥量);其他错误可能会造成内核锁起/恐慌,可以使用kdump/crash 进行调试 |
用户态互斥量 | 使用率 | valgrind --tool=drd --exclusive-threshold=...... (持有时间);对加锁到解锁这段的函数时间进行动态跟踪 |
用户态互斥量 | 饱和度 | valgrind --tool=drd 可以根据持有时间推断竞争的情况;对同步函数进行动态跟踪得到等待时间;进行剖析(oprofile、PEL......)用户调用栈得到旋转等待的情况 |
用户态互斥量 | 错误 | valgrind --tool=drd 提示的各种错误;动态跟踪 pthread_mutex_lock() 的返回值,如EAGAIN、EINVAL、EPERM、EDEADLK、ENOMEM、EOWNEREAD 等 |
任务容量 | 使用率 | top/htop ,Tasks 项(当前);sysctl kernel.threads-max 项,/proc/sys/kernel/threads-max(最大值) |
任务容量 | 饱和度 | 被阻塞在内存分配上的线程数;这个时候页面扫描器应该正在运行(sar -B,pgscan* ),或者使用动态跟踪检查 |
任务容量 | 错误 | “can't fork()” 错误;用户态线程:pthread_create() 错误返回值如 EAGAIN、EINVAL......;内核组:动态跟踪 kernel_thread() 函数的 ENOMEM 返回值 |
文件描述符 | 使用率 | 系统范围:sar -v ,file-nr 项和 /proc/sys/fs/file-max 相比较;dstat --fs ,files项;或者是 /proc/sys/fs/file-nr每个线程: ls /proc/PID/fd | wc -l 对比 ulimt -n |
文件描述符 | 饱和度 | 这一项没有意义 |
文件描述符 | 错误 | 在返回文件描述符的系统调用上(例如 open()、accept()......)使用 strace errno == EMFILE |
内核锁分析以前是通过
lockmeter
进行的,它有一个接口调用 lockstat。