Linux I/O性能分析

索引节点和目录项

Linux文件系统为每个文件都分配两个数据结构,索引节点(index node)和目录项(directory entry),它们主要用来记录文件的元信息和目录结构

  • 索引节点(简称inode)用来记录文件的元数据,比如inode编号、文件大小、访问权限、修改日期、数据的位置等。索引节点和文件一一对应,它跟文件内容一样会被持久化存储到磁盘中。
  • 目录项(简称dentry)用来记录文件的名字、索引节点指针以及与其他目录项的关联关系。多个关联的目录项,就构成了文件系统的目录结构。不同于索引节点,目录项是由内核维护的一个内存数据结构,所以通常也被叫做目录项缓存。

索引节点是每个文件的唯一标志,而目录项维护的正是文件系统的树状结构。目录项和索引节点的关系是多对一,你可以简单理解为,一个文件可以有多个别名。举个例子,通过硬链接为文件创建的别名,就会对应不同的目录项,不过这些目录项本质上还是链接同一个文件,所以,它们的索引节点相同。索引节点和目录项纪录了文件的元数据,以及文件间的目录关系,那么具体来说,文件数据到底是怎么存储的呢?是不是直接写到磁盘中就好了呢?实际上,磁盘读写的最小单位是扇区,然而扇区只有 512B 大小,如果每次都读写这么小的单位,效率一定很低。所以,文件系统又把连续的扇区组成了逻辑块,然后每次都以逻辑块为最小单元,来管理数据。常见的逻辑块大小为 4KB,也就是由连续的 8 个扇区组成。

Linux I/O性能分析_第1张图片

  • 目录项本身就是一个内存缓存,而索引节点则是存储在磁盘中的数据。在前面的 Buffer 和 Cache 原理中,我曾经提到过,为了协调慢速磁盘与快速 CPU 的性能差异,文件内容会缓存到页缓存 Cache 中
  • 磁盘在执行文件系统格式化时,会被分成三个存储区域,超级块、索引节点区和数据块区。其中,超级块,存储整个文件系统的状态。索引节点区,用来存储索引节点。数据块区,则用来存储文件数据。

内核使用slab机制管理目录项和索引节点的缓存,可以通过/proc/slabinfo文件查看所有目录项和各种文件系统索引节点的缓存情况。其中dentry行表示目录项缓存,inode_cache行表示 VFS 索引节点缓存,其余的则是各种文件系统的索引节点缓存

[root@VM-4-5-centos lighthouse]# cat /proc/slabinfo | grep -E '^#|dentry|inode'
# name                 : tunables    : slabdata   
isofs_inode_cache     46     46    704   23    4 : tunables    0    0    0 : slabdata      2      2      0
ext4_inode_cache    4644   4644   1176   27    8 : tunables    0    0    0 : slabdata    172    172      0
jbd2_inode           128    128     64   64    1 : tunables    0    0    0 : slabdata      2      2      0
mqueue_inode_cache     16     16   1024   16    4 : tunables    0    0    0 : slabdata      1      1      0
hugetlbfs_inode_cache     24     24    680   12    2 : tunables    0    0    0 : slabdata      2      2      0
inotify_inode_mark    102    102     80   51    1 : tunables    0    0    0 : slabdata      2      2      0
sock_inode_cache     253    253    704   23    4 : tunables    0    0    0 : slabdata     11     11      0
proc_inode_cache    3168   3322    728   22    4 : tunables    0    0    0 : slabdata    151    151      0
shmem_inode_cache    882    882    768   21    4 : tunables    0    0    0 : slabdata     42     42      0
inode_cache        14688  14748    656   12    2 : tunables    0    0    0 : slabdata   1229   1229      0
dentry             27531  27531    192   21    1 : tunables    0    0    0 : slabdata   1311   1311      0
selinux_inode_security  16626  16626     40  102    1 : tunables    0    0    0 : slabdata    163    163      0

在实际性能分析中更常使用slabtop命令茶查找占用内存最多的缓存类型

[root@VM-4-5-centos lighthouse]#slabtop

Active / Total Objects (% used)    : 223087 / 225417 (99.0%)
 Active / Total Slabs (% used)      : 7310 / 7310 (100.0%)
 Active / Total Caches (% used)     : 138 / 207 (66.7%)
 Active / Total Size (% used)       : 50536.41K / 51570.46K (98.0%)
 Minimum / Average / Maximum Object : 0.01K / 0.23K / 8.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 29295  28879  98%    0.19K   1395       21      5580K dentry
 27150  27150 100%    0.13K    905       30      3620K kernfs_node_cache
 26112  25802  98%    0.03K    204      128       816K kmalloc-32
 23010  23010 100%    0.10K    590       39      2360K buffer_head
 16626  16626 100%    0.04K    163      102       652K selinux_inode_security
 14856  14764  99%    0.64K   1238       12      9904K inode_cache
  9894   9894 100%    0.04K     97      102       388K ext4_extent_status
  6698   6698 100%    0.23K    394       17      1576K vm_area_struct
  5508   5508 100%    1.15K    204       27      6528K ext4_inode_cache
  5120   5120 100%    0.02K     20      256        80K kmalloc-16
  4672   4630  99%    0.06K     73       64       292K kmalloc-64
  4564   4564 100%    0.57K    326       14      2608K radix_tree_node
  4480   4480 100%    0.06K     70       64       280K anon_vma_chain
  4096   4096 100%    0.01K      8      512        32K kmalloc-8
  3570   3570 100%    0.05K     42       85       168K ftrace_event_field
  3168   2967  93%    0.71K    144       22      2304K proc_inode_cache
  3003   2961  98%    0.19K    143       21       572K kmalloc-192
  2898   2422  83%    0.09K     63       46       252K anon_vma
  2368   1944  82%    0.25K    148       16       592K filp
  2080   2075  99%    0.50K    130       16      1040K kmalloc-512
  2016   2016 100%    0.07K     36       56       144K Acpi-Operand
  1760   1760 100%    0.12K     55       32       220K kmalloc-128
  1596   1596 100%    0.09K     38       42       152K kmalloc-96
  1472   1472 100%    0.09K     32       46       128K trace_event_file

虚拟文件系统

目录项、索引节点、逻辑块以及超级块,构成了 Linux 文件系统的四大基本要素。不过,为了支持各种不同的文件系统,Linux 内核在用户进程和文件系统的中间,又引入了一个抽象层,也就是虚拟文件系统 VFS(Virtual File System)。VFS 定义了一组所有文件系统都支持的数据结构和标准接口。这样,用户进程和内核中的其他子系统,只需要跟 VFS 提供的统一接口进行交互就可以了,而不需要再关心底层各种文件系统的实现细节。

Linux I/O性能分析_第2张图片

磁盘顺序IO与随机IO

磁盘IO性能指标

使用率、饱和度、IOPS、吞吐量以及响应时间等。这五个指标,是衡量磁盘性能的基本指标

  • 使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。
  • 饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。
  • IOPS(Input/Output Per Second),是指每秒的 I/O 请求数。
  • 吞吐量,是指每秒的 I/O 请求大小。
  • 响应时间,是指 I/O 请求从发出到收到响应的间隔时间。

fio

我推荐用性能测试工具 fio ,来测试磁盘的 IOPS、吞吐量以及响应时间等核心指标

iostat

iostat 是最常用的磁盘 I/O 性能观测工具,它提供了每个磁盘的使用率、IOPS、吞吐量等各种常见的性能指标,当然,这些指标实际上来自 /proc/diskstats


# -d -x表示显示所有磁盘I/O的指标
$ iostat -d -x 1 
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.00      0.00     0.00     0.00   0.00   0.00    0.00    0.00   0.00     0.00     0.00   0.00   0.00 
loop1            0.00    0.00      0.00      0.00     0.00     0.00   0.00   0.00    0.00    0.00   0.00     0.00     0.00   0.00   0.00 
sda              0.00    0.00      0.00      0.00     0.00     0.00   0.00   0.00    0.00    0.00   0.00     0.00     0.00   0.00   0.00 
sdb              0.00    0.00      0.00      0.00     0.00     0.00   0.00   0.00    0.00    0.00   0.00     0.00     0.00   0.00   0.00 

Linux I/O性能分析_第3张图片

这些指标中,你要注意:
%util ,就是我们前面提到的磁盘 I/O 使用率;
r/s+ w/s ,就是 IOPS;rkB/s+wkB/s ,就是吞吐量;
r_await+w_await ,就是响应时间。
在观测指标时,也别忘了结合请求的大小( rareq-sz 和 wareq-sz)一起分析。

进程 I/O 观测

pidstat


$ pidstat -d 1 
13:39:51      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command 
13:39:52      102       916      0.00      4.00      0.00       0  rsyslogd

从 pidstat 的输出你能看到,它可以实时查看每个进程的 I/O 情况,包括下面这些内容。
用户 ID(UID)和进程 ID(PID) 。
每秒读取的数据大小(kB_rd/s) ,单位是 KB。
每秒发出的写请求数据大小(kB_wr/s) ,单位是 KB。
每秒取消的写请求数据大小(kB_ccwr/s) ,单位是 KB。
块 I/O 延迟(iodelay),包括等待同步块 I/O 和换入块 I/O 结束的时间,单位是时钟周期。

除了可以用 pidstat 实时查看,根据 I/O 大小对进程排序,也是性能分析中一个常用的方法。这一点,我推荐另一个工具, iotop。它是一个类似于 top 的工具,你可以按照 I/O 大小对进程排序,然后找到 I/O 较大的那些进程


$ 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 

你可能感兴趣的:(linux)