Linux性能优化实战学习笔记:第十六讲
一、free数据的来源
1、碰到看不明白的指标时该怎么办吗?
不懂就去查手册。用 man 命令查询 free 的文档、就可以找到对应指标的详细说明。比如,我们执行 man fre...
2、free数据的来源
[root@ccb-installment-api ~]# man free NAME free - Display amount of free and used memory in the system SYNOPSIS free [options] DESCRIPTION free displays the total amount of free and used physical and swap memory in the system, as well as the buffers and caches used by the kernel. The information is gathered by parsing /proc/meminfo. The displayed columns are: total Total installed memory (MemTotal and SwapTotal in /proc/meminfo) used Used memory (calculated as total - free - buffers - cache) free Unused memory (MemFree and SwapFree in /proc/meminfo) shared Memory used (mostly) by tmpfs (Shmem in /proc/meminfo, available on kernels 2.6.32, displayed as zero if not available) buffers Memory used by kernel buffers (Buffers in /proc/meminfo) cache Memory used by the page cache and slabs (Cached and Slab in /proc/meminfo) buff/cache
Buffers 是内核缓冲区用到的内存,对应的是/proc/meminfo 中的 Buffers 值。
Cache 是内核页缓存和 Slab 用到的内存,对应的是/proc/meminfo 中的 Cached 与 与 SReclaimable 之和。
3、关于磁盘和文件的区别
本来以为大家都懂了,所以没有细讲。磁盘是一个块设备,可以划分为不同的分区;在分区之上再创建文件系统,挂载到某个目录,之后才可以在这个目录中读写文件。
其实 Linux 中“一切皆文件”,而文章中提到的“文件”是普通文件,磁盘是块设备文件,这些大家可以执行 "ls -l <路径>" 查看它们的区别(输出的含义如果不懂请 man ls 查询)。
在读写普通文件时,会经过文件系统,由文件系统负责与磁盘交互;而读写磁盘或者分区时,就会跳过文件系统,也就是所谓的“裸I/O“。这两种读写方式所使用的缓存是不同的,也就是文中所讲的 Cache 和 Buffer 区别。
关于文件系统、磁盘以及 I/O 的原理,大家不要着急,后面 I/O 模块还会讲的。
二、proc文件系统
1、proc文件系统介绍
1、我在前面 CPU 性能模块就曾经提到过/proc 是 Linux 内核提供的一种特殊文件系统,是用户跟内核交互的接口比方说,用户可以从 /proc 中查询内核的运行状态和配置选项,查询进程的运行状
态、统计数据等,
2、当然,你也可以通过/proc 来修改内核的配置
3、proc文件系统同时也是很多性能工具的最终数据来源,比如我们刚看到的free,就是通过读取/proc/meminfo ,得到内存的使用情况。
2、man proc
继续说回 /proc/meminfo,既然 Buffers、Cached、SReclaimable 这几个指标不容易理解,那我们还得继续查 proc 文件系统,获取它们的详细定义。
执行 man proc ,你就可以得到 proc 文件系统的详细文档
Buffers %lu Relatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so). Cached %lu In-memory cache for files read from the disk (the page cache). Doesn't include SwapCached. ... SReclaimable %lu (since Linux 2.6.19) Part of Slab, that might be reclaimed, such as caches. SUnreclaim %lu (since Linux 2.6.19) Part of Slab, that cannot be reclaimed on memory pressure.
Buffers 是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB左右),这样,内核就可以把分散的写集中起来
统一优化磁盘的写入,比如可以把多次小的写合并成单词大的写等等
Cached 是从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,
而不需要再次访问缓慢的磁盘。
SReclaimable 是 Slab 的一部分。Slab包括两部分,其中的可回收部分,用 SReclaimable 记录;而不可回收部分,用 SUnreclaim 记录。
3、你真的理解Buffer 和 Cache吗?
第一个问题:Buffer 的文档没有提到这是磁盘读数据还是写数据的缓存,而在很多网络搜索的结果中都会提到 Buffer 只是对将要写入磁盘数据的缓存。那反过来说,
它会不会也缓存从磁盘中读取的数据呢?
第二个问题:文档中提到,Cache 是对从文件读取数据的缓存,那么它是不是也会缓存写文件的数据呢?
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
三、磁盘和文件写案例
1、磁盘写案例
1、清理缓存
# 清理文件页、目录项、Inodes 等各种缓存 $ echo 3 > /proc/sys/vm/drop_caches
2、终端一运行vmstat
[root@luoahong ~]# vmstat 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 7544944 0 151620 0 0 976 176 347 585 4 12 83 1 0 0 0 0 7544944 0 151636 0 0 0 0 100 145 0 0 100 0 0 0 0 0 7544944 0 151636 0 0 0 0 109 156 0 0 100 0 0 0 0 0 7544944 0 151636 0 0 0 0 104 154 0 0 100 0 0 0 0 0 7544944 0 151636 0 0 0 0 113 153 0 0 100 0 0
正常情况下,空闲系统中,你应该看到的是,这几个值在多次结果中一直保持不变。
3、终端2执行 dd 命令,通过读取随机设备,生成一个 500MB 大小的文件
dd if=/dev/urandom of=/tmp/file bs=1M count=500
4、第一个终端,观察 Buffer 和 Cache 的变化情况
[root@luoahong ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 4 0 0 7270684 0 424228 0 0 708 128 283 453 3 10 87 1 0 1 0 0 7213892 0 480700 0 0 0 0 2022 742 0 51 49 0 0 1 0 0 7161068 0 533556 0 0 0 0 1846 734 0 51 49 0 0 1 0 0 7109112 0 585616 0 0 0 0 2014 733 0 51 49 0 0 1 0 0 7058272 0 636312 0 0 0 0 1874 734 0 50 50 0 0 0 0 0 7018616 0 676764 0 0 20 0 1511 590 0 38 62 0 0 0 0 0 7018616 0 676764 0 0 0 0 103 145 0 0 100 0 0 4 0 0 7017232 0 677820 0 0 9 159744 514 188 0 10 87 3 0 0 0 0 7018288 0 676844 0 0 0 0 211 189 0 2 98 0 0 0 0 0 7018288 0 676844 0 0 0 0 122 151 0 0 100 0 0 0 0 0 7018288 0 676844 0 0 0 0 139 176 1 1 98 1 0 0 0 0 7018288 0 676844 0 0 0 0 98 137 0 0 100 0 0 1 0 0 7018288 0 676844 0 0 0 13312 171 175 0 2 98 0 0 0 0 0 7018448 0 676684 0 0 0 338944 906 257 0 17 83 0 0 0 0 0 7018448 0 676684 0 0 0 0 106 148 0 0 100 0 0 0 0 0 7018448 0 676684 0 0 0 0 100 141 0 1 99 0 0 ...
buff 和 cache 就是我们前面看到的 Buffers和 Cache,单位是 KB。
bi 和 bo 则分别表示块设备读取和写入的大小,单位为块因为 Linux 中块的大小是 1KB,所以这个单位也就等价于 KB/s。
1、Cache 在不停地增长,而 Buffer 基本保持不变。
2、在 Cache 刚开始增长时,块设备 I/O 很少,bi 只出现了一次 708 KB/s,bo 则只有一次128KB。而过一段时间后,才会出现大量的块设备写,比如bo变成了 159744。
3、当 dd 命令结束后,Cache 不再增长,但块设备写还会持持续一段时间,并且,多次 I/O 写的结果加起来,才是 dd 要写的 500M 的数据。
2、文件写案例
1、清理缓存
# 清理文件页、目录项、Inodes 等各种缓存 $ echo 3 > /proc/sys/vm/drop_caches
2、终端一运行vmstat
[root@luoahong ~]# vmstat 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 7006732 4 682672 0 0 159 301 100 152 1 3 97 0 0 0 0 0 7006740 4 682672 0 0 0 0 84 127 0 0 100 0 0 0 0 0 7006740 4 682672 0 0 16 43 61 105 0 0 100 0 0 0 0 0 7006740 4 682672 0 0 0 0 61 119 0 0 100 0 0
3、终端2向磁盘分区 /dev/sdb1 写入 2GB 的随机数据
dd if=/dev/urandom of=/dev/sdb1 bs=1M count=2048
4、第一个终端,观察 Buffer 和 Cache 的变化情况
[root@luoahong ~]# vmstat 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 6977304 534528 179348 0 0 154 286 100 148 1 3 97 0 0 2 0 0 6904740 603176 182796 0 0 0 53248 1972 633 0 60 40 0 0 1 0 0 6845544 659456 185888 0 0 0 0 1058 126 0 50 50 0 0 1 0 0 6787756 714328 188876 0 0 0 0 1102 216 0 50 50 0 0 1 0 0 6731240 768000 191680 0 0 0 0 1352 713 0 51 49 0 0 1 0 0 6675808 820568 194512 0 0 0 53248 1600 616 0 56 44 0 0 3 0 0 6622872 870884 197056 0 0 0 278274 2679 151 0 79 21 0 0 3 0 0 6574708 916448 199632 0 0 0 501504 3947 180 0 100 0 0 0 1 0 0 6517416 970824 202640 0 0 0 31230 1217 97 0 53 47 0 0 1 0 0 6459256 1026048 205516 0 0 0 0 1033 89 0 50 50 0 0 1 0 0 6401220 1081212 208592 0 0 0 0 1034 78 0 50 50 0 0 1 0 0 6343588 1135928 211524 0 0 0 0 1045 103 0 50 50 0 0 1 0 0 6286420 1190236 214284 0 0 0 0 1359 740 0 51 49 0 0 1 0 0 6234832 1239040 216988 0 0 0 304872 2838 299 0 81 19 0 0 1 0 0 6177044 1294048 219956 0 0 0 1 1041 86 0 50 50 0 0 1 0 0 6119380 1348628 222920 0 0 0 0 1030 81 0 50 50 0 0 1 0 0 6061128 1403904 225876 0 0 0 0 1034 78 0 50 50 0 0 3 0 0 6023576 1439248 227952 0 0 360 215042 2618 668 0 59 41 0 0 0 0 0 7539344 0 151992 0 0 1086 1828 418 302 1 11 88 0 0 0 0 0 7539372 0 152032 0 0 0 4 117 139 1 1 99 0 0 0 0 0 7539372 0 152032 0 0 0 0 57 88 0 0 100 0 0 0 0 0 7539248 0 152032 0 0 40 0 96 123 0 1 99 0 0
虽然同时写数据,写磁盘跟写文件的现象还是不同的,写磁盘时(也就是 bo 大于0时)Buffer 和 Cache 都在增长,但显然 Buffer的增长快得多
这说明,写磁盘用到了大量的Buffer,这跟我们在文件中查到的定义是一样的。
写文件时会用到 Cache 缓存数据,而写磁盘则会用到Buffer 来缓存数据。所以,回到刚刚的问题,虽然文档上只提到,Cache 是文件读的缓存,但实际上,Cache 也会缓存写文件时的数据。
四、磁盘和文件读案例
1、磁盘写案例
1、清理缓存
# 清理文件页、目录项、Inodes 等各种缓存 $ echo 3 > /proc/sys/vm/drop_caches
2、终端一运行vmstat
[root@luoahong ~]# vmstat 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 7539868 0 151596 0 0 126 820 96 130 0 3 96 0 0 0 0 0 7539908 0 151636 0 0 0 0 49 94 0 1 99 1 0 0 0 0 7539908 0 151636 0 0 0 0 61 105 0 0 100 0 0 0 0 0 7539908 0 151636 0 0 0 0 58 95 0 0 100 0 0
3、终端2从文件 /tmp/file 中,读取数据写入空设备
dd if=/tmp/file of=/dev/null
4、第一个终端,观察 Buffer 和 Cache 的变化情况
[root@luoahong ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 3 0 0 7237960 0 454648 0 0 245 803 96 128 0 3 96 0 0 1 0 0 7164180 0 528288 0 0 72704 0 1193 141 0 50 50 0 0 1 0 0 7090400 0 602004 0 0 73728 0 1063 73 0 52 48 0 0 0 0 0 7029028 0 663684 0 0 61616 0 1763 573 0 52 48 0 0 0 0 0 7029044 0 663684 0 0 0 0 65 101 1 0 99 0 0
观察 vmstat 的输出,你会发现读取文件时(也就是bi 大于0时),Buffer 保持不变,而 Cache 则在不停增长。这跟我们查到的定义“Cache是对文件读的页缓存”是一致的。
2、文件写案例
1、清理缓存
# 清理文件页、目录项、Inodes 等各种缓存 $ echo 3 > /proc/sys/vm/drop_caches
2、终端一运行vmstat
[root@luoahong ~]# vmstat 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 7541212 0 151572 0 0 296 720 90 121 0 3 97 0 0 0 0 0 7541212 0 151576 0 0 0 0 54 108 0 0 100 0 0 0 0 0 7541212 0 151576 0 0 0 0 45 79 0 0 100 0 0 0 0 0 7541212 0 151576 0 0 0 0 54 94 0 1 100 0 0
3、终端2从磁盘分区 /dev/sda1 中读取数据,写入空设备
dd if=/tmp/file of=/dev/null
4、第一个终端,观察 Buffer 和 Cache 的变化情况
[root@luoahong ~]# vmstat 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 7540956 0 151576 0 0 287 698 88 118 0 3 97 0 0 0 0 0 7540956 0 151584 0 0 0 0 88 139 0 0 100 0 0 0 0 0 7540956 0 151584 0 0 0 0 85 136 0 0 100 0 0 1 0 0 6869864 667140 151900 0 0 669772 0 1343 207 0 36 64 0 0 0 0 0 6484500 1054720 152876 0 0 385024 0 742 332 0 15 85 0 0 0 0 0 6484500 1054720 152876 0 0 0 0 134 214 1 0 99 0 0 0 0 0 6484500 1054720 152876 0 0 0 0 78 141 0 1 99 1 0 0 0 0 6484500 1054720 152876 0 0 0 0 112 205 0 0 100 0 0 0 0 0 6484500 1054720 152876 0 0 0 0 106 168 0 0 100 0 0 0 0 0 6484500 1054720 152876 0 0 0 0 67 121 0 1 100 0 0
观察 vmstat 的输出,你会发现读取文件时(也就是bi大于0时),Buffer和Cache 都在增长。但显然Buffer增长的快很多,这说明度磁盘时,数据缓存到了Buffer中
Buffer 既可以用作“将要写入磁盘数据的缓存”,也可以用作“从磁盘读取数据的缓存”。
Cache 既可以用作“从文件读取数据的页缓存”,也可以用作“写文件的页缓存”。
这样,我们就回答了案例开始前的两个问题。
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。