日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

16 | 基础篇:怎么理解内存中的Buffer和Cache?

發布時間:2024/9/3 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 16 | 基础篇:怎么理解内存中的Buffer和Cache? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節,我們梳理了 Linux 內存管理的基本原理,并學會了用 free 和 top 等工具,來查看系統和進程的內存使用情況。在今天的內容開始之前,我們先來回顧一下系統的內存使用情況,比如下面這個 free 輸出界面:# 注意不同版本的 free 輸出可能會有所不同 $ freetotal used free shared buff/cache available Mem: 8169348 263524 6875352 668 1030472 7611064 Swap: 0 0 0顯然,這個界面包含了物理內存 Mem 和交換分區 Swap 的具體使用情況,比如總內存、已用內存、緩存、可用內存等。其中緩存是 Buffer 和 Cache 兩部分的總和 。這里的大部分指標都比較容易理解,但 Buffer 和 Cache 可能不太好區分。從字面上來說,Buffer 是緩沖區,而 Cache 是緩存,兩者都是數據在內存中的臨時存儲。那么,你知道這兩種“臨時存儲”有什么區別嗎?注:今天內容接下來的部分,Buffer 和 Cache 我會都用英文來表示,避免跟文中的“緩存”一詞混淆。而文中的“緩存”,則通指內存中的臨時存儲。

free 數據的來源

在我正式講解兩個概念前,你可以先想想,你有沒有什么途徑來進一步了解它們?除了中文翻譯直接得到概念,別忘了,Buffer 和 Cache 還是我們用 free 獲得的指標。還記得我之前講過的,碰到看不明白的指標時該怎么辦嗎?估計你想起來了,不懂就去查手冊。用 man 命令查詢 free 的文檔,就可以找到對應指標的詳細說明。比如,我們執行 man free ,就可以看到下面這個界面。buffersMemory used by kernel buffers (Buffers in /proc/meminfo)cache Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)buff/cacheSum of buffers and cache從 free 的手冊中,你可以看到 buffer 和 cache 的說明。
  • Buffers 是內核緩沖區用到的內存,對應的是 /proc/meminfo 中的 Buffers 值。
  • Cache 是內核頁緩存和 Slab 用到的內存,對應的是 /proc/meminfo 中的 Cached 與 SReclaimable 之和。
這里的說明告訴我們,這些數值都來自 /proc/meminfo,但更具體的 Buffers、Cached 和 SReclaimable 的含義,還是沒有說清楚。要注意,網上的結論可能是對的,但是很可能跟你的環境并不匹配。最簡單來說,同一個指標的具體含義,就可能因為內核版本、性能工具版本的不同而有挺大差別。這也是為什么,我總在專欄中強調通用思路和方法,而不是讓你死記結論。對于案例實踐來說,機器環境就是我們的最大限制。那么,有沒有更簡單、更準確的方法,來查詢它們的含義呢?

proc 文件系統

我在前面 CPU 性能模塊就曾經提到過,/proc 是 Linux 內核提供的一種特殊文件系統,是用戶跟內核交互的接口。比方說,用戶可以從 /proc 中查詢內核的運行狀態和配置選項,查詢進程的運行狀態、統計數據等,當然,你也可以通過 /proc 來修改內核的配置。proc 文件系統同時也是很多性能工具的最終數據來源。比如我們剛才看到的 free ,就是通過讀取 /proc/meminfo ,得到內存的使用情況。繼續說回 /proc/meminfo,既然 Buffers、Cached、SReclaimable 這幾個指標不容易理解,那我們還得繼續查 proc 文件系統,獲取它們的詳細定義。執行 man proc ,你就可以得到 proc 文件系統的詳細文檔。注意這個文檔比較長,你最好搜索一下(比如搜索 meminfo),以便更快定位到內存部分。Buffers %luRelatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so).Cached %luIn-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 記錄。
好了,我們終于找到了這三個指標的詳細定義。到這里,你是不是長舒一口氣,滿意地想著,總算弄明白 Buffer 和 Cache 了。不過,知道這個定義就真的理解了嗎?這里我給你提了兩個問題,你先想想能不能回答出來。
  • 第一個問題,Buffer 的文檔沒有提到這是磁盤讀數據還是寫數據的緩存,而在很多網絡搜索的結果中都會提到 Buffer 只是對將要寫入磁盤數據的緩存。那反過來說,它會不會也緩存從磁盤中讀取的數據呢?
  • 第二個問題,文檔中提到,Cache 是對從文件讀取數據的緩存,那么它是不是也會緩存寫文件的數據呢?
為了解答這兩個問題,接下來,我將用幾個案例來展示, Buffer 和 Cache 在不同場景下的使用情況。

案例

跟前面實驗一樣,今天的案例也是基于 Ubuntu 18.04,當然,其他 Linux 系統也適用。我的案例環境是這樣的。機器配置:2 CPU,8GB 內存。預先安裝 sysstat 包,如 apt install sysstat。之所以要安裝 sysstat ,是因為我們要用到 vmstat ,來觀察 Buffer 和 Cache 的變化情況。雖然從 /proc/meminfo 里也可以讀到相同的結果,但畢竟還是 vmstat 的結果更加直觀。另外,這幾個案例使用了 dd 來模擬磁盤和文件的 I/O,所以我們也需要觀測 I/O 的變化情況。上面的工具安裝完成后,你可以打開兩個終端,連接到 Ubuntu 機器上。準備環節的最后一步,為了減少緩存的影響,記得在第一個終端中,運行下面的命令來清理系統緩存:# 清理文件頁、目錄項、Inodes 等各種緩存 $ echo 3 > /proc/sys/vm/drop_caches這里的 /proc/sys/vm/drop_caches ,就是通過 proc 文件系統修改內核行為的一個示例,寫入 3 表示清理文件頁、目錄項、Inodes 等各種緩存。這幾種緩存的區別你暫時不用管,后面我們都會講到。

場景 1:磁盤和文件寫案例

我們先來模擬第一個場景。首先,在第一個終端,運行下面這個 vmstat 命令:# 每隔 1 秒輸出 1 組數據 $ 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 0 0 0 7743608 1112 92168 0 0 0 0 52 152 0 1 100 0 00 0 0 7743608 1112 92168 0 0 0 0 36 92 0 0 100 0 0輸出界面里, 內存部分的 buff 和 cache ,以及 io 部分的 bi 和 bo 就是我們要關注的重點。
  • buff 和 cache 就是我們前面看到的 Buffers 和 Cache,單位是 KB。
  • bi 和 bo 則分別表示塊設備讀取和寫入的大小,單位為塊 / 秒。因為 Linux 中塊的大小是 1KB,所以這個單位也就等價于 KB/s。
正常情況下,空閑系統中,你應該看到的是,這幾個值在多次結果中一直保持不變。接下來,到第二個終端執行 dd 命令,通過讀取隨機設備,生成一個 500MB 大小的文件:$ dd if=/dev/urandom of=/tmp/file bs=1M count=500然后再回到第一個終端,觀察 Buffer 和 Cache 的變化情況:procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 7499460 1344 230484 0 0 0 0 29 145 0 0 100 0 01 0 0 7338088 1752 390512 0 0 488 0 39 558 0 47 53 0 01 0 0 7158872 1752 568800 0 0 0 4 30 376 1 50 49 0 01 0 0 6980308 1752 747860 0 0 0 0 24 360 0 50 50 0 00 0 0 6977448 1752 752072 0 0 0 0 29 138 0 0 100 0 00 0 0 6977440 1760 752080 0 0 0 152 42 212 0 1 99 1 0 ...0 1 0 6977216 1768 752104 0 0 4 122880 33 234 0 1 51 49 00 1 0 6977440 1768 752108 0 0 0 10240 38 196 0 0 50 50 0通過觀察 vmstat 的輸出,我們發現,在 dd 命令運行時, Cache 在不停地增長,而 Buffer 基本保持不變。再進一步觀察 I/O 的情況,你會看到,
  • 在 Cache 剛開始增長時,塊設備 I/O 很少,bi 只出現了一次 488 KB/s,bo 則只有一次 4KB。而過一段時間后,才會出現大量的塊設備寫,比如 bo 變成了 122880。
  • 當 dd 命令結束后,Cache 不再增長,但塊設備寫還會持續一段時間,并且,多次 I/O 寫的結果加起來,才是 dd 要寫的 500M 的數據。
把這個結果,跟我們剛剛了解到的 Cache 的定義做個對比,你可能會有點暈乎。為什么前面文檔上說 Cache 是文件讀的頁緩存,怎么現在寫文件也有它的份?這個疑問,我們暫且先記下來,接著再來看另一個磁盤寫的案例。兩個案例結束后,我們再統一進行分析。不過,對于接下來的案例,我必須強調一點:下面的命令對環境要求很高,需要你的系統配置多塊磁盤,并且磁盤分區 /dev/sdb1 還要處于未使用狀態。如果你只有一塊磁盤,千萬不要嘗試,否則將會對你的磁盤分區造成損壞。如果你的系統符合標準,就可以繼續在第二個終端中,運行下面的命令。清理緩存后,向磁盤分區 /dev/sdb1 寫入 2GB 的隨機數據:# 首先清理緩存 $ echo 3 > /proc/sys/vm/drop_caches # 然后運行 dd 命令向磁盤分區 /dev/sdb1 寫入 2G 數據 $ dd if=/dev/urandom of=/dev/sdb1 bs=1M count=2048然后,再回到終端一,觀察內存和 I/O 的變化情況: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 7584780 153592 97436 0 0 684 0 31 423 1 48 50 2 01 0 0 7418580 315384 101668 0 0 0 0 32 144 0 50 50 0 01 0 0 7253664 475844 106208 0 0 0 0 20 137 0 50 50 0 01 0 0 7093352 631800 110520 0 0 0 0 23 223 0 50 50 0 01 1 0 6930056 790520 114980 0 0 0 12804 23 168 0 50 42 9 01 0 0 6757204 949240 119396 0 0 0 183804 24 191 0 53 26 21 01 1 0 6591516 1107960 123840 0 0 0 77316 22 232 0 52 16 33 0從這里你會看到,雖然同是寫數據,寫磁盤跟寫文件的現象還是不同的。寫磁盤時(也就是 bo 大于 0 時),Buffer 和 Cache 都在增長,但顯然 Buffer 的增長快得多。這說明,寫磁盤用到了大量的 Buffer,這跟我們在文檔中查到的定義是一樣的。對比兩個案例,我們發現,寫文件時會用到 Cache 緩存數據,而寫磁盤則會用到 Buffer 來緩存數據。所以,回到剛剛的問題,雖然文檔上只提到,Cache 是文件讀的緩存,但實際上,Cache 也會緩存寫文件時的數據。

場景 2:磁盤和文件讀案例

了解了磁盤和文件寫的情況,我們再反過來想,磁盤和文件讀的時候,又是怎樣的呢?我們回到第二個終端,運行下面的命令。清理緩存后,從文件 /tmp/file 中,讀取數據寫入空設備:# 首先清理緩存 $ echo 3 > /proc/sys/vm/drop_caches # 運行 dd 命令讀取文件數據 $ dd if=/tmp/file of=/dev/null然后,再回到終端一,觀察內存和 I/O 的變化情況:procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r b swpd free buff cache si so bi bo in cs us sy id wa st0 1 0 7724164 2380 110844 0 0 16576 0 62 360 2 2 76 21 00 1 0 7691544 2380 143472 0 0 32640 0 46 439 1 3 50 46 00 1 0 7658736 2380 176204 0 0 32640 0 54 407 1 4 50 46 00 1 0 7626052 2380 208908 0 0 32640 40 44 422 2 2 50 46 0觀察 vmstat 的輸出,你會發現讀取文件時(也就是 bi 大于 0 時),Buffer 保持不變,而 Cache 則在不停增長。這跟我們查到的定義“Cache 是對文件讀的頁緩存”是一致的。那么,磁盤讀又是什么情況呢?我們再運行第二個案例來看看。首先,回到第二個終端,運行下面的命令。清理緩存后,從磁盤分區 /dev/sda1 中讀取數據,寫入空設備:# 首先清理緩存 $ echo 3 > /proc/sys/vm/drop_caches # 運行 dd 命令讀取文件 $ dd if=/dev/sda1 of=/dev/null bs=1M count=1024然后,再回到終端一,觀察內存和 I/O 的變化情況:procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 7225880 2716 608184 0 0 0 0 48 159 0 0 100 0 00 1 0 7199420 28644 608228 0 0 25928 0 60 252 0 1 65 35 00 1 0 7167092 60900 608312 0 0 32256 0 54 269 0 1 50 49 00 1 0 7134416 93572 608376 0 0 32672 0 53 253 0 0 51 49 00 1 0 7101484 126320 608480 0 0 32748 0 80 414 0 1 50 49 0觀察 vmstat 的輸出,你會發現讀磁盤時(也就是 bi 大于 0 時),Buffer 和 Cache 都在增長,但顯然 Buffer 的增長快很多。這說明讀磁盤時,數據緩存到了 Buffer 中。當然,我想,經過上一個場景中兩個案例的分析,你自己也可以對比得出這個結論:讀文件時數據會緩存到 Cache 中,而讀磁盤時數據會緩存到 Buffer 中。到這里你應該發現了,雖然文檔提供了對 Buffer 和 Cache 的說明,但是仍不能覆蓋到所有的細節。比如說,今天我們了解到的這兩點:
  • Buffer 既可以用作“將要寫入磁盤數據的緩存”,也可以用作“從磁盤讀取數據的緩存”。
  • Cache 既可以用作“從文件讀取數據的頁緩存”,也可以用作“寫文件的頁緩存”。
這樣,我們就回答了案例開始前的兩個問題。簡單來說,Buffer 是對磁盤數據的緩存,而 Cache 是文件數據的緩存,它們既會用在讀請求中,也會用在寫請求中。

小結

今天,我們一起探索了內存性能中 Buffer 和 Cache 的詳細含義。Buffer 和 Cache 分別緩存磁盤和文件系統的讀寫數據。從寫的角度來說,不僅可以優化磁盤和文件的寫入,對應用程序也有好處,應用程序可以在數據真正落盤前,就返回去做其他工作。從讀的角度來說,既可以加速讀取那些需要頻繁訪問的數據,也降低了頻繁 I/O 對磁盤的壓力。思考我們已經知道,可以使用 ps、top 或者 proc 文件系統,來獲取進程的內存使用情況。那么,如何統計出所有進程的物理內存使用量呢?提示:要避免重復計算多個進程同時占用的內存,像是頁緩存、共享內存這類。如果你把 ps、top 得到的數據直接相加,就會出現重復計算的問題。這里,我推薦從 /proc/< pid >/smaps 入手。前面內容里,我并沒有直接講過 /proc/< pid >smaps 文件中各個指標含義,所以,需要你自己動手查 proc 文件系統的文檔,解讀并回答這個問題。

總結

以上是生活随笔為你收集整理的16 | 基础篇:怎么理解内存中的Buffer和Cache?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。