1. 程式人生 > >Linux性能優化實戰:怎麽理解內存中的Buffer和Cache?(16)

Linux性能優化實戰:怎麽理解內存中的Buffer和Cache?(16)

inux tro parsing 內核 echo buffers block sed 性能優化

一、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)