这篇文章上次修改于 765 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

1 性能指标

1.1 文件系统 I/O 性能

  • 存储空间的使用情况:包括容量、使用量以及剩余空间等
  • 索引节点的使用情况:包括容量、使用量以及剩余量等。
  • 缓存使用情况:包括页缓存、目录项缓存、索引节点缓存以及各个具体文件系统(如 ext4、XFS 等)的缓存。
  • 文件 I/O:包括 IOPS(包括 r/s 和 w/s)、响应时间(延迟)以及吞吐量(B/s)等。

1.2 磁盘 I/O 性能指标

  • 使用率,是指磁盘忙处理 I/O 请求的百分比。过高的使用率(比如超过 60%)通常意味着磁盘 I/O 存在性能瓶颈。
  • IOPS(Input/Output Per Second),是指每秒的 I/O 请求数。
  • 吞吐量,是指每秒的 I/O 请求大小。
  • 响应时间,是指从发出 I/O 请求到收到响应的间隔时间。
  • 缓冲区(Buffer)。

2 性能工具

2.1 从性能指标出发

2.1.1 文件系统空间

文件系统空间容量、使用量和剩余量:

$ df -h /dev/sda1 
Filesystem      Size  Used Avail Use% Mounted on 
/dev/sda1        29G  3.1G   26G  11% / 

2.1.2 索引节点空间

索引节点空间容量、使用量和剩余量:

$ df -i /dev/sda1 
Filesystem      Inodes  IUsed   IFree IUse% Mounted on 
/dev/sda1      3870720 157460 3713260    5% / 

2.1.3 页缓存和可回收 slab 缓存

vmstat 输出的 Cache,是页缓存和可回收 Slab 缓存的和:

$ vmstat 
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  97228 153468 526340    0    0   388   121   55  373  2  1 96  1  0

页缓存和可回收 Slab 缓存:

$ cat /proc/meminfo | grep -E "SReclaimable|Cached"
Cached:           469120 kB  # 页缓存
SwapCached:            0 kB
SReclaimable:      57004 kB  # 可回收 Slab 缓存

页缓存:

$ sar -r
Linux 4.15.0-142-generic (VM-0-5-ubuntu)        10/17/2021      _x86_64_        (1 CPU)

19:08:15     LINUX RESTART      (1 CPU)

07:15:01 PM kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
07:25:01 PM    101416    612068    907248     89.95    153084    467004   1298244    128.71    510612    270692       300
07:35:01 PM     97212    610608    911452     90.36    153460    469276   1300748    128.96    516968    267944       360
Average:        99314    611338    909350     90.15    153272    468140   1299496    128.83    513790    269318       330

2.1.4 缓冲区

sar -r、vmstat、/proc/meminfo

$ cat /proc/meminfo | grep -E Buff
Buffers:          153560 kB

2.1.5 目录项、索引节点、文件系统缓存

目录项和索引节点缓存:

$ cat /proc/slabinfo | grep -E '^#|dentry|inode' 
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail> 
xfs_inode              0      0    960   17    4 : tunables    0    0    0 : slabdata      0      0      0 
... 
ext4_inode_cache   32104  34590   1088   15    4 : tunables    0    0    0 : slabdata   2306   2306      0hugetlbfs_inode_cache     13     13    624   13    2 : tunables    0    0    0 : slabdata      1      1      0 
sock_inode_cache    1190   1242    704   23    4 : tunables    0    0    0 : slabdata     54     54      0 
shmem_inode_cache   1622   2139    712   23    4 : tunables    0    0    0 : slabdata     93     93      0 
proc_inode_cache    3560   4080    680   12    2 : tunables    0    0    0 : slabdata    340    340      0 
inode_cache        25172  25818    608   13    2 : tunables    0    0    0 : slabdata   1986   1986      0 
dentry             76050 121296    192   21    1 : tunables    0    0    0 : slabdata   5776   5776      0 

目录项、索引节点、文件系统缓存:

# 按下c按照缓存大小排序,按下a按照活跃对象数排序 
$ slabtop 
Active / Total Objects (% used)    : 277970 / 358914 (77.4%) 
Active / Total Slabs (% used)      : 12414 / 12414 (100.0%) 
Active / Total Caches (% used)     : 83 / 135 (61.5%) 
Active / Total Size (% used)       : 57816.88K / 73307.70K (78.9%) 
Minimum / Average / Maximum Object : 0.01K / 0.20K / 22.88K 

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME 
69804  23094   0%    0.19K   3324       21     13296K dentry 
16380  15854   0%    0.59K   1260       13     10080K inode_cache 
58260  55397   0%    0.13K   1942       30      7768K kernfs_node_cache 
   485    413   0%    5.69K     97        5      3104K task_struct 
  1472   1397   0%    2.00K     92       16      2944K kmalloc-2048 

2.1.6 磁盘性能

磁盘 I/O 使用率、IOPS、吞吐量、响应时间、I/O 平均大小和等待队列长度。

# -d -x表示显示所有磁盘I/O的指标
$ iostat -d -x 1
Linux 4.15.0-142-generic (VM-0-5-ubuntu)        10/17/2021      _x86_64_        (1 CPU)

Device            r/s     w/s     rkB/s     wkB/s   rrqm/s   wrqm/s  %rrqm  %wrqm r_await w_await aqu-sz rareq-sz wareq-sz  svctm  %util
loop0            0.00    0.00      0.01      0.00     0.00     0.00   0.00   0.00    0.50    0.00   0.00    19.55     0.00   0.07   0.00
scd0             0.03    0.00      1.36      0.00     0.00     0.00   0.08   0.00    0.39    0.00   0.00    39.76     0.00   0.27   0.00
vda              5.27    8.02    382.48    120.21     0.00     5.30   0.03  39.80    1.69    1.18   0.01    72.54    14.99   0.24   0.32
  • aqu-sz:平均请求队列长度。
  • rareq-sz:平均读请求大小。
$ sar -d
Linux 4.15.0-142-generic (VM-0-5-ubuntu)        10/17/2021      _x86_64_        (1 CPU)

19:08:15     LINUX RESTART      (1 CPU)

07:15:01 PM       DEV       tps     rkB/s     wkB/s   areq-sz    aqu-sz     await     svctm     %util
07:25:01 PM    dev7-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:25:01 PM   dev11-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:25:01 PM  dev252-0      2.60      0.03     20.41      7.87      0.00      0.86      0.11      0.03
07:35:01 PM    dev7-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:35:01 PM   dev11-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:35:01 PM  dev252-0      2.84      2.70     21.13      8.39      0.00      0.93      0.10      0.03
07:45:01 PM    dev7-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:45:01 PM   dev11-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:45:01 PM  dev252-0      2.51      0.03     18.69      7.47      0.00      0.86      0.09      0.02
07:55:01 PM    dev7-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:55:01 PM   dev11-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:55:01 PM  dev252-0      2.47      0.27     18.37      7.53      0.00      1.10      0.10      0.03
Average:       dev7-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:      dev11-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:     dev252-0      2.60      0.76     19.65      7.84      0.00      0.94      0.10      0.03

2.1.7 进程 I/O 大小和 I/O 延迟

$ pidstat -d
Linux 4.15.0-142-generic (VM-0-5-ubuntu)        10/17/2021      _x86_64_        (1 CPU)

08:03:32 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
08:03:32 PM     0         1     -1.00     -1.00     -1.00     112  systemd
08:03:32 PM     0        34     -1.00     -1.00     -1.00      20  kswapd0
08:03:32 PM     0       354     -1.00     -1.00     -1.00   40064  jbd2/vda1-8
$ iotop
Total DISK READ :       0.00 B/s | Total DISK WRITE :       7.85 K/s 
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s 
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND 
15055 be/3 root        0.00 B/s    7.85 K/s  0.00 %  0.00 % systemd-journald 

2.1.8 进程 I/O 系统调用跟踪

$ strace -p 18940 
strace: Process 18940 attached 
...
mmap(NULL, 314576896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0f7aee9000 
mmap(NULL, 314576896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0f682e8000 
write(3, "2018-12-05 15:23:01,709 - __main"..., 314572844 
) = 314572844 
munmap(0x7f0f682e8000, 314576896)       = 0 
write(3, "\n", 1)                       = 1 
munmap(0x7f0f7aee9000, 314576896)       = 0 
close(3)                                = 0 
stat("/tmp/logtest.txt.1", {st_mode=S_IFREG|0644, st_size=943718535, ...}) = 0 

2.2 从工具出发

  • iostat:磁盘 I/O 使用率、IOPS、吞吐量、响应时间、I/O 平均大小和等待队列长度。
  • pidstat:进程 I/O 大小和 I/O 延迟。
  • sar:磁盘 I/O 使用率、IOPS、吞吐量、响应时间、I/O 平均大小和等待队列长度。
  • iotop:按 I/O 大小对进程排序。
  • slabtop:目录项、索引节点和文件系统缓存大小。
  • /proc/slabinfo:目录项、索引节点和文件系统缓存大小。
  • /proc/meminfo:页缓存和可回收 Slab 缓存。
  • /proc/diskstats:磁盘的 IOPS、吞吐量和延迟。
  • vmstat:缓存和缓冲区汇总。
  • strace:跟踪进程的 I/O 系统调用。
  • perf:跟踪内核中的 I/O 事件。
  • df:磁盘空间和索引节点使用量和余量。
  • mount:文件系统的挂载路径和挂载参数。
  • du:目录占用的磁盘空间大小。

3 如何迅速分析 I/O 的性能瓶颈

分析思路:

  • 用 iostat 发现磁盘 I/O 性能瓶颈。
  • 用 pistat 分析出导致磁盘 I/O 性能瓶颈的进程。
  • 分析进程的 I/O 行为。
  • 结合应用程序分析 I/O 的来源。

参考

倪朋飞. Linux 性能优化实战.