上节说道,Buffer和Cache是对磁盘和文件系统的读写缓存加速

那么如果没有做好这一部分的操作,会出现什么问题呢?这就是本章探讨的问题

开始前,首先要说明,本章采用的衡量方式,是常见的缓存的命中率

然后是缓存的命中查看方式,常见的工具有

cachestat和cachetop

cachestat查看整个操作系统的读写命中

cachetop提供了每个进程的缓存命中

对应的cachestat的使用,基本如下

cachestat 1 3 1秒的间隔,输出3组缓存数据

上面的表格中的数据指标有

TOTAL 总的IO次数

MISSES 缓存的未命中次数

HITS 缓存命中的次数

DIRTIES 新增到缓存中的脏页数

BUFFERS_MB Buffers的大小,以MB为单位

CACHED_MB Cache的大小,MB为单位

cachetop的运行界面

$ cachetop

11:58:50 Buffers MB: 258 / Cached MB: 347 / Sort: HITS / Order: ascending

PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%

13029 root     python                  1        0        0     100.0%       0.0%

默认按照HITS排序,其中不同的之后READ_HIT 和 WRITE_HIT

读和写的缓存命中率

最后就是获取指定文件在内存中的缓存大小,使用pcstat工具,查看文件在内存汇总的缓存大小和比例

pcstat基于Go安装的

使用很简单

$ pcstat /bin/ls

+———+—————-+————+———–+———+

| Name    | Size (bytes)   | Pages      | Cached    | Percent |

|———+—————-+————+———–+———|

| /bin/ls | 133792         | 33         | 0         | 000.000 |

+———+—————-+————+———–+———+

获取输出

Cached是缓存大小,Percent是缓存比例,都是0

我们接下来进行讲解案例

首先是dd命令获取一个临时文件,方便读取

# 生成一个512MB的临时文件

$ dd if=/dev/sda1 of=file bs=1M count=512

# 清理缓存

$ echo 3 > /proc/sys/vm/drop_caches

运行pcstat,确定文件不在缓存

$ pcstat file

+——-+—————-+————+———–+———+

| Name  | Size (bytes)   | Pages      | Cached    | Percent |

|——-+—————-+————+———–+———|

| file  | 536870912      | 131072     | 0         | 000.000 |

+——-+—————-+————+———–+———+

然后尝试查看对应的缓存情况

cachetop 5

然后运行dd查看对应的读取速度

$ dd if=file of=/dev/null bs=1M

512+0 records in

512+0 records out

536870912 bytes (537 MB, 512 MiB) copied, 16.0509 s, 33.4 MB/s

读的性能是33.4MB/S

这基本可以肯定从磁盘中读取的文件

然后我们看一下cachetop的缓存命中情况

PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%

\.\.\.

3264 root     dd                  37077    37330        0      49.8%      50.2%

发现是先走了磁盘,后走了缓存

然后,再次尝试读取文件

$ dd if=file of=/dev/null bs=1M

512+0 records in

512+0 records out

536870912 bytes (537 MB, 512 MiB) copied, 0.118415 s, 4.5 GB/s

发现读取性能为 4.5GB/S 基本证明走了缓存

cachetop的输出证明了猜测

10:45:22 Buffers MB: 4 / Cached MB: 719 / Sort: HITS / Order: ascending

PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%

\.\.\.

32642 root     dd                 131637        0        0     100.0%       0.0%

cachetop有了不小的变化,读的缓存命中率是100%

然后,利用pcstat查看file的缓存情况

$ pcstat file

+——-+—————-+————+———–+———+

| Name  | Size (bytes)   | Pages      | Cached    | Percent |

|——-+—————-+————+———–+———|

| file  | 536870912      | 131072     | 131072    | 100.000 |

+——-+—————-+————+———–+———+

说明file基本被缓存起来了,加速了文件读取的性能,反过来也说明了dd会走缓存,单纯利用dd测试不可取

然后这一次,我们运行一个程序,从文件中读取32MB的数据

我们尝试运行cachetop 5 每5秒输出一次案例

在运行程序后,继续查看

程序会输出,每次读取32MB的数据,时间需要0.9秒

这不正常

16:39:18 Buffers MB: 73 / Cached MB: 281 / Sort: HITS / Order: ascending

PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%

21881 root     app                  1024        0        0     100.0%       0.0%

HITS的命中只有1024个,这说明5秒只有4MB的命中

说明每秒0.8MB的命中

那么是否是没有走缓存,直接尝试读取的磁盘呢?

从源码中查看,的确使用了直接IO

那么修改之后,我们再一次查看对应的输出

cachetop的输出如下

16:40:08 Buffers MB: 73 / Cached MB: 281 / Sort: HITS / Order: ascending

PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%

22106 root     app                 40960        0        0     100.0%       0.0%

读的命中率为100%,命中率却成了40960个,换算一下正是32MB

IO操作的时候,充分利用系统缓存可以提升性能,观察缓存命中率

上面的问题也说明了,cachetop工具并不把直接IO算进来

今天,我们说了两个工具,一个cachestat和cachetop

以及对应的使用

发表评论

邮箱地址不会被公开。 必填项已用*标注