如何利用系统缓存提高应用程序运行效率

Buffer和Cache分别缓存的是对磁盘和文件系统的读写数据。

  • 从写的角度来说,不仅可以优化磁盘和文件的写入,对应用程序也有好处,应用程序可以在数据真正落盘前,就返回去做其他工作。

  • 从读的角度来说,不仅可以提高那些频繁访问数据的读取速度,也降低了频繁I/O对磁盘的压力。

缓存命中率

使用cachestat 和 cachetop 查看系统缓存命中情况,这两个工具都是 bcc 软件包的一部分,它们基于 Linux 内核的 eBPF(extended Berkeley Packet Filters)机制,来跟踪内核中管理的缓存,并输出缓存的使用和命中情况。

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD
1
2
3
echo "deb https://repo.iovisor.org/apt/xenial xenial main" | sudo tee /etc/apt/sources.list.d/iovisor.list
sudo apt-get update
sudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)
1
$ export PATH=$PATH:/usr/share/bcc/tools

执行

1
2
3
4
5
root@linux:~# cachestat 1 3
HITS MISSES DIRTIES HITRATIO BUFFERS_MB CACHED_MB
0 0 0 0.00% 16 2574
0 0 0 0.00% 16 2574
77 1 0 98.72% 16 2574

参数说明:

  • TOTAL,表示总的I/O次数;

  • MISSES,表示缓存未命中的次数;

  • HITS,表示缓存命中的次数;

  • DIRTIES, 表示新增到缓存中的脏页数;

  • BUFFERS_ MB表示Buffers的大小,以MB为单位;

  • CACHED_ _MB表示Cache的大小,以MB为单位。

cachetop 与top 类似,默认按照缓存的命中次数(HITS)排序,展示了每个进程的缓存命中情况。具体到每一个指标,这里的 HITS、MISSES 和 DIRTIES ,跟 cachestat 里的含义一样,分别代表间隔时间内的缓存命中次数、未命中次数以及新增到缓存中的脏页数。而 READ_HIT 和 WRITE_HIT ,分别表示读和写的缓存命中率。

指定文件的缓存大小

1
2
3
4
5
6
root@linux:~# pcstat /bin/ls
|----------+----------------+------------+-----------+---------|
| Name | Size | Pages | Cached | Percent |
|----------+----------------+------------+-----------+---------|
| /bin/ls | 133792 | 33 | 33 | 100.000 |
|----------+----------------+------------+-----------+---------|

案例

生成临时文件

1
2
3
4
root@linux:~# dd if=/dev/sdc of=file bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 0.392026 s, 1.4 GB/s

使用pcstat 查看文件缓存,并清空换后再次查看确保cached 为 0

1
2
3
4
5
6
7
8
9
10
11
12
13
root@linux:~# pcstat file
|----------+----------------+------------+-----------+---------|
| Name | Size | Pages | Cached | Percent |
|----------+----------------+------------+-----------+---------|
| file | 536870912 | 131072 | 131072 | 100.000 |
|----------+----------------+------------+-----------+---------|
root@linux:~# echo 3 > /proc/sys/vm/drop_caches
root@linux:~# pcstat file
|----------+----------------+------------+-----------+---------|
| Name | Size | Pages | Cached | Percent |
|----------+----------------+------------+-----------+---------|
| file | 536870912 | 131072 | 0 | 000.000 |
|----------+----------------+------------+-----------+---------|

执行

1
2
3
4
root@linux:~# dd if=/dev/sdc of=file bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 5.35013 s, 100 MB/s

执行cachetop 5 查看dd 的读写命中都是 25%

执行下面命令

1
2
3
4
oot@linux:~# dd if=file of=/dev/null bs=1M
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 5.02737 s, 107 MB/s

查看缓存 发现只命中 50%

image-20190328145851319

执行下面命令

1
2
3
4
root@linux:~# dd if=file of=/dev/null bs=1M
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 0.142228 s, 3.8 GB/s

image-20190328145947901

可以发现 第二次执行 dd 每秒写速度3.8GB, 第一次是107MB。这就是充分利用了缓存而达到的效果,因此使用dd 进行测试时候需要注意缓存而影响测试效果不准确。