上节说道,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
以及对应的使用