Linux性能優化實戰:怎麽理解內存中的Buffer和Cache?(16)
一、free數據的來源
1、碰到看不明白的指標時該怎麽辦嗎?
不懂就去查手冊。用 man 命令查詢 free 的文檔、就可以找到對應指標的詳細說明。比如,我們執行 man fre...
2、free數據的來源
[[email protected] ~]# 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
[[email protected] ~]# 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 的變化情況
[[email protected] ~]# 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
[[email protected] ~]# 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 的變化情況
[[email protected] ~]# 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
[[email protected] ~]# 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 的變化情況
[[email protected] ~]# 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
[[email protected] ~]# 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 的變化情況
[[email protected] ~]# 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 是文件數據的緩存,它們既會用在讀請求中,也會用在寫請求中。
Linux性能優化實戰:怎麽理解內存中的Buffer和Cache?(16)