Linux内存指标中buffers和cached小结
Contents
一背景说明
我们在Linux系统上,通过free来查看系统内存资源使用情况时,会看到buffers和cache指标:
[root@localhost ~]# free -m total used free shared buff/cache available Mem: 7983 1436 802 625 5744 5632 Swap: 8063 0 8063 [root@localhost ~]#
那么这两个指标分别表示什么呢?
二 实践验证
0 机器信息
[root@localhost ~]# uname -rm 3.10.0-514.el7.x86_64 x86_64 [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) [root@localhost ~]# df -Th 文件系统 类型 容量 已用 可用 已用% 挂载点 /dev/mapper/cl-root xfs 50G 11G 40G 22% / devtmpfs devtmpfs 3.9G 0 3.9G 0% /dev tmpfs tmpfs 3.9G 4.0K 3.9G 1% /dev/shm tmpfs tmpfs 3.9G 25M 3.9G 1% /run tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/sdc1 xfs 200G 97G 104G 49% /pgdata /dev/sdb5 xfs 100G 96G 4.5G 96% /pgdata2 /dev/sda1 xfs 1014M 121M 894M 12% /boot /dev/mapper/cl-home xfs 42G 33G 8.2G 81% /home tmpfs tmpfs 799M 0 799M 0% /run/user/0 [root@localhost ~]#
每次执行实践操作之前,我们都先把page cache、dentry、inode缓存清空。
[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches [root@localhost ~]#
1 写文件操作
#terminal 1,执行下述操作 [root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches [root@localhost ~]# [root@localhost ~]# dd if=/dev/urandom of=/tmp/tempfile bs=1M count=4000 记录了4000+0 的读入 记录了4000+0 的写出 4194304000字节(4.2 GB)已复制,331.938 秒,12.6 MB/秒 [root@localhost ~]# # 在另外一个terminal 2里,执行vmstat -SM 1 ,观察内存的使用变化情况 [root@localhost ~]# vmstat -SM 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 22 0 0 5390 0 769 0 0 21 121 19 13 19 1 80 0 0 ... 27 1 0 5305 0 825 0 0 22020 40 6846 1022 97 3 1 0 0 29 2 0 5262 0 859 0 0 24901 64 7938 1371 97 3 0 0 0 ...
其中,dd if=/dev/urandom of=/tmp/tempfile bs=1M count=4000表示的是读取input file,每个块大小1M,一共4000个块,然后写出output file到/tmp/tempfile。
然后,我们可以看到vmstat的输出中,memory字段中的buffer并没有发生变化,这是cache字段随着时间推移,逐渐变大。同时,看到IO字段下的bo也跟着变大。
2 读文件操作
#terminal 1,执行下述操作 [root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches [root@localhost ~]# dd if=/tmp/tempfile bs=1M count=4000 of=/dev/null 记录了4000+0 的读入 记录了4000+0 的写出 4194304000字节(4.2 GB)已复制,47.3821 秒,88.5 MB/秒 [root@localhost ~]# #terminal 2:执行vmstat -SM 1 ,观察内存的使用变化情况 [root@localhost ~]# vmstat -SM 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 5 0 0 5811 0 741 0 0 25 126 15 18 19 1 80 0 0 2 0 0 5810 0 741 0 0 16 0 4057 609 30 1 69 0 0 4 0 0 5801 0 751 0 0 9784 104 6087 1500 39 2 52 7 0 1 0 0 5790 0 762 0 0 11728 528 2797 759 20 2 78 1 0 4 1 0 5723 0 847 0 0 86200 32 4226 637 38 3 49 11 0 1 1 0 5636 0 934 0 0 89632 80 4341 1516 32 3 55 10 0 6 1 0 5528 0 1043 0 0 111136 24 4619 646 41 3 46 10 0 3 1 0 5419 0 1151 0 0 111584 80 4488 1014 33 3 55 9 0 42 2 0 5325 0 1247 0 0 96976 712 9514 3965 77 6 14 3 0 24 5 0 5246 0 1325 0 0 79360 930 10904 3283 95 4 1 0 0 8 2 0 5139 0 1433 0 0 109924 1248 11521 4333 85 4 5 7 0 3 1 0 5056 0 1517 0 0 85808 491 5589 1966 33 2 55 10 0 3 2 0 4940 0 1632 0 0 118184 152 4171 3718 27 2 60 11 0 1 1 0 4832 0 1739 0 0 109968 352 4522 3255 33 3 52 12 0 3 1 0 4780 0 1792 0 0 53272 104 3849 588 36 1 53 10 0 ...
这时,我们模拟从文件读出文件,并写出到系统黑洞/dev/null里,依然是写4G大小的数据。
这时,我们看到buff字段依然没有变化,同时cache不断增大,伴随着io字段的bi跟着变大。
这里的IO字段中的bi和bo分别表示block input,block output,其单位是KB,我们通过vmstat -SM 1表示的是每秒输出一次结果,也就意味着,bi和bo字段的值表示的是KB/s。
3 写磁盘操作
💊💊💊,这个操作要慎重,需要机器有除了操作系统之外,还有独立的磁盘。我这里有个独立的盘是/dev/sdb。因为该写入磁盘操作,会破坏磁盘中已有的数据。
#terminal 1,先清空缓存,然后执行写磁盘操作 [root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches [root@localhost ~]# dd if=/dev/urandom of=/dev/sdb5 bs=1M count=4000 记录了4000+0 的读入 记录了4000+0 的写出 4194304000字节(4.2 GB)已复制,371.912 秒,11.3 MB/秒 [root@localhost ~]# #terminal 2,监控内存和IO使用情况 [root@localhost ~]# vmstat -SM 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 5791 0 796 0 0 28 128 18 18 19 1 80 0 0 0 0 0 5791 0 796 0 0 0 76 394 227 3 0 97 0 0 ... 1 3 0 5468 93 1022 0 0 52064 432 8610 4376 23 15 49 14 0 4 2 0 5431 99 1054 0 0 32760 24 10092 7159 10 16 56 18 0 ... 12 2 0 601 3736 2158 0 0 8 10416 10131 1632 19 14 49 18 0 28 0 0 591 3747 2157 0 0 0 20968 8782 1803 64 12 21 3 0 #terminal 3,我们也可以通过free -m 来查看内存情况 [root@localhost ~]# free -m -w -s 1 -c 40 total used free shared buffers cache available Mem: 7983 1423 1665 624 2975 1920 5587 Swap: 8063 0 8063 ... total used free shared buffers cache available Mem: 7983 1510 1108 624 3308 2056 5497 Swap: 8063 0 8063 ... total used free shared buffers cache available Mem: 7983 1425 333 624 4000 2224 5585 Swap: 8063 0 8063 ^C [root@localhost ~]#
此时,我们看到系统的cache字段变化不明显,反而buffers从0逐渐变大,直到变为4000M,和我们写入磁盘的数据大小一致结束。互相印证了。IO字段的bo逐渐变大。
4 读磁盘操作
#terminal 1,先清空缓存,然后执行读磁盘操作 [root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches [root@localhost ~]# dd if=/dev/sdb sdb sdb1 sdb5 [root@localhost ~]# dd if=/dev/sdb5 of=/dev/null bs=1M count=4000 记录了4000+0 的读入 记录了4000+0 的写出 4194304000字节(4.2 GB)已复制,41.243 秒,102 MB/秒 [root@localhost ~]# #terminal 2,监控内存和IO使用情况 [root@localhost ~]# vmstat -SM 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 5592 0 973 0 0 29 130 20 19 19 1 79 0 0 0 0 0 5591 0 973 0 0 800 136 1028 471 7 0 92 0 0 0 0 0 5591 0 974 0 0 16 0 485 328 0 0 99 0 0 0 0 0 5589 0 976 0 0 1836 1400 7996 2061 72 2 26 0 0 0 1 0 5540 46 977 0 0 47740 304 642 494 0 1 94 5 0 0 1 0 5432 154 976 0 0 110600 96 1212 431 7 2 80 11 0 ... 1 1 0 2204 3262 1097 0 0 106504 96 1451 579 9 2 78 11 0 0 1 0 2096 3370 1097 0 0 110852 2703 1331 996 4 2 83 11 0 0 1 0 1996 3470 1097 0 0 102400 216 1106 447 7 1 80 11 0 0 1 0 1935 3530 1097 0 0 61480 65 477 405 0 1 87 12 0 0 1 0 1835 3630 1097 0 0 102480 843 1191 509 7 1 80 11 0 4 2 0 1754 3710 1098 0 0 82832 176 1359 981 1 2 86 11 0 0 1 0 1634 3830 1098 0 0 122880 792 7575 1664 69 2 23 5 0 1 1 0 1535 3930 1098 0 0 102408 176 613 452 0 1 87 12 0 0 0 0 1459 4006 1098 0 0 78012 64 1214 460 7 1 84 8 0 1 0 0 1459 4006 1098 0 0 8 24 307 305 0 0 100 0 0
看到,读磁盘操作时,buffers从0逐渐增长到4000M,同时随着读磁盘操作完成之后,buffer不再变化。同时,看到IO字段的bi升高,bo变化不明显。
三 小结
1 内存指标中buffer和cache最终的含义
buffer用来缓存磁盘读、写数据的缓存;
cache用来缓存文件读、写数据的缓存;
2 磁盘读写和文件读写的区别
上述我们分别通过使用:
dd if=/dev/urandom of=/tmp/tempfile bs=1M count=4000;写/tmp/tempfile文件; free -m 结果中io字段的bo会跟着增加;
dd if=/tmp/tempfile of=/dev/null bs=1M count=4000;读/tmp/tempfile文件; free -m 结果中io字段的bi会跟着增加;
dd if=/dev/urandom of=/dev/sdb5 bs=1M count=4000;写磁盘分区;free -m 结果中io字段的bo会跟着增加;
dd if=/dev/sdb5 of=/dev/null bs=1M count=4000;读磁盘分区;free -m 结果中io字段的bi会跟着增加;
其中,当我们直接对磁盘、磁盘分区进行读写时,是绕过操作系统层面的,不走文件系统层面的缓存;这就如同Oracle数据库使用裸设备作为存储设备的场景一样;
当我们对磁盘上的文件进行读写时,它是要走操作系统层面的缓存的,需要经过文件系统层面。
3 认真读了man free命令的帮助信息
其中,收获的是:free -m -w -t 1 -c 40;
-m:表示的是以MB为单位输出结果;
-w:表示的以宽行格式分别显示buffers和cache字段的值;
-t:表示每秒输出1次结果;
-c:表示的累计输出40次;
如果加上-t的话,会在每次输出结果后面,再加一行total的信息。
[root@localhost ~]# free -m -w -t 1 -c 40 -t total used free shared buffers cache available Mem: 7983 1440 800 625 3592 2148 5629 Swap: 8063 0 8063 Total: 16047 1440 8864 total used free shared buffers cache available Mem: 7983 1440 796 625 3592 2153 5629 Swap: 8063 0 8063 Total: 16047 1440 8860 ^C [root@localhost ~]#
接下来,要继续认真读一下man proc; man ps; man top;