17 | 案例篇:如何利用系统缓存优化程序的运行效率?
生活随笔
收集整理的這篇文章主要介紹了
17 | 案例篇:如何利用系统缓存优化程序的运行效率?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節,我們學習了內存性能中 Buffer 和 Cache 的概念。簡單復習一下,Buffer 和 Cache 的設計目的,是為了提升系統的 I/O 性能。它們利用內存,充當起慢速磁盤與快速 CPU 之間的橋梁,可以加速 I/O 的訪問速度。 Buffer 和 Cache 分別緩存的是對磁盤和文件系統的讀寫數據。 從寫的角度來說,不僅可以優化磁盤和文件的寫入,對應用程序也有好處,應用程序可以在數據真正落盤前,就返回去做其他工作。 從讀的角度來說,不僅可以提高那些頻繁訪問數據的讀取速度,也降低了頻繁 I/O 對磁盤的壓力。 既然 Buffer 和 Cache 對系統性能有很大影響,那我們在軟件開發的過程中,能不能利用這一點,來優化 I/O 性能,提升應用程序的運行效率呢? 答案自然是肯定的。今天,我就用幾個案例幫助你更好地理解緩存的作用,并學習如何充分利用這些緩存來提高程序效率。 為了方便你理解,Buffer 和 Cache 我仍然用英文表示,避免跟“緩存”一詞混淆。而文中的“緩存”,通指數據在內存中的臨時存儲。
緩存命中率
在案例開始前,你應該習慣性地先問自己一個問題,你想要做成某件事情,結果應該怎么評估?比如說,我們想利用緩存來提升程序的運行效率,應該怎么評估這個效果呢?換句話說,有沒有哪個指標可以衡量緩存使用的好壞呢? 我估計你已經想到了,緩存的命中率。所謂緩存命中率,是指直接通過緩存獲取數據的請求次數,占所有數據請求次數的百分比。 命中率越高,表示使用緩存帶來的收益越高,應用程序的性能也就越好。 實際上,緩存是現在所有高并發系統必需的核心模塊,主要作用就是把經常訪問的數據(也就是熱點數據),提前讀入到內存中。這樣,下次訪問時就可以直接從內存讀取數據,而不需要經過硬盤,從而加快應用程序的響應速度。 這些獨立的緩存模塊通常會提供查詢接口,方便我們隨時查看緩存的命中情況。不過 Linux 系統中并沒有直接提供這些接口,所以這里我要介紹一下,cachestat 和 cachetop ,它們正是查看系統緩存命中情況的工具。- cachestat 提供了整個操作系統緩存的讀寫命中情況。
- cachetop 提供了每個進程的緩存命中情況。
- TOTAL ,表示總的 I/O 次數;
- MISSES ,表示緩存未命中的次數;
- HITS ,表示緩存命中的次數;
- DIRTIES, 表示新增到緩存中的臟頁數;
- BUFFERS_MB 表示 Buffers 的大小,以 MB 為單位;
- CACHED_MB 表示 Cache 的大小,以 MB 為單位。
指定文件的緩存大小
除了緩存的命中率外,還有一個指標你可能也會很感興趣,那就是指定文件在內存中的緩存大小。你可以使用 pcstat 這個工具,來查看文件在內存中的緩存大小以及緩存比例。 pcstat 是一個基于 Go 語言開發的工具,所以安裝它之前,你首先應該安裝 Go 語言,你可以點擊這里下載安裝。 安裝完 Go 語言,再運行下面的命令安裝 pcstat: $ export GOPATH=~/go $ export PATH=~/go/bin:$PATH $ go get golang.org/x/sys/unix $ go get github.com/tobert/pcstat/pcstat 全部安裝完成后,你就可以運行 pcstat 來查看文件的緩存情況了。比如,下面就是一個 pcstat 運行的示例,它展示了 /bin/ls 這個文件的緩存情況: $ pcstat /bin/ls +---------+----------------+------------+-----------+---------+ | Name | Size (bytes) | Pages | Cached | Percent | |---------+----------------+------------+-----------+---------| | /bin/ls | 133792 | 33 | 0 | 000.000 | +---------+----------------+------------+-----------+---------+ 這個輸出中,Cached 就是 /bin/ls 在緩存中的大小,而 Percent 則是緩存的百分比。你看到它們都是 0,這說明 /bin/ls 并不在緩存中。 接著,如果你執行一下 ls 命令,再運行相同的命令來查看的話,就會發現 /bin/ls 都在緩存中了: $ ls $ pcstat /bin/ls +---------+----------------+------------+-----------+---------+ | Name | Size (bytes) | Pages | Cached | Percent | |---------+----------------+------------+-----------+---------| | /bin/ls | 133792 | 33 | 33 | 100.000 | +---------+----------------+------------+-----------+---------+ 知道了緩存相應的指標和查看系統緩存的方法后,接下來,我們就進入今天的正式案例。 跟前面的案例一樣,今天的案例也是基于 Ubuntu 18.04,當然同樣適用于其他的 Linux 系統。 機器配置:2 CPU,8GB 內存。 預先按照上面的步驟安裝 bcc 和 pcstat 軟件包,并把這些工具的安裝路徑添加到到 PATH 環境變量中。 預先安裝 Docker 軟件包,比如 apt-get install docker.io案例一
第一個案例,我們先來看一下上一節提到的 dd 命令。 dd 作為一個磁盤和文件的拷貝工具,經常被拿來測試磁盤或者文件系統的讀寫性能。不過,既然緩存會影響到性能,如果用 dd 對同一個文件進行多次讀取測試,測試的結果會怎么樣呢? 我們來動手試試。首先,打開兩個終端,連接到 Ubuntu 機器上,確保 bcc 已經安裝配置成功。 然后,使用 dd 命令生成一個臨時文件,用于后面的文件讀取測試: # 生成一個 512MB 的臨時文件 $ dd if=/dev/sda1 of=file bs=1M count=512 # 清理緩存 $ echo 3 > /proc/sys/vm/drop_caches 繼續在第一個終端,運行 pcstat 命令,確認剛剛生成的文件不在緩存中。如果一切正常,你會看到 Cached 和 Percent 都是 0: $ pcstat file +-------+----------------+------------+-----------+---------+ | Name | Size (bytes) | Pages | Cached | Percent | |-------+----------------+------------+-----------+---------| | file | 536870912 | 131072 | 0 | 000.000 | +-------+----------------+------------+-----------+---------+ 還是在第一個終端中,現在運行 cachetop 命令: # 每隔 5 秒刷新一次數據 $ cachetop 5 這次是第二個終端,運行 dd 命令測試文件的讀取速度: $ dd if=file of=/dev/null bs=1M 512+0 records in 512+0 records out 536870912 bytes (537 MB, 512 MiB) copied, 16.0509 s, 33.4 MB/s 從 dd 的結果可以看出,這個文件的讀性能是 33.4 MB/s。由于在 dd 命令運行前我們已經清理了緩存,所以 dd 命令讀取數據時,肯定要通過文件系統從磁盤中讀取。 不過,這是不是意味著, dd 所有的讀請求都能直接發送到磁盤呢? 我們再回到第一個終端, 查看 cachetop 界面的緩存命中情況: PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT% \.\.\.3264 root dd 37077 37330 0 49.8% 50.2% 從 cachetop 的結果可以發現,并不是所有的讀都落到了磁盤上,事實上讀請求的緩存命中率只有 50% 。 接下來,我們繼續嘗試相同的測試命令。先切換到第二個終端,再次執行剛才的 dd 命令: $ dd if=file of=/dev/null bs=1M 512+0 records in 512+0 records out 536870912 bytes (537 MB, 512 MiB) copied, 0.118415 s, 4.5 GB/s 看到這次的結果,有沒有點小驚訝?磁盤的讀性能居然變成了 4.5 GB/s,比第一次的結果明顯高了太多。為什么這次的結果這么好呢? 不妨再回到第一個終端,看看 cachetop 的情況: 10:45:22 Buffers MB: 4 / Cached MB: 719 / Sort: HITS / Order: ascending PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT% \.\.\.32642 root dd 131637 0 0 100.0% 0.0% 顯然,cachetop 也有了不小的變化。你可以發現,這次的讀的緩存命中率是 100.0%,也就是說這次的 dd 命令全部命中了緩存,所以才會看到那么高的性能。 然后,回到第二個終端,再次執行 pcstat 查看文件 file 的緩存情況: $ pcstat file +-------+----------------+------------+-----------+---------+ | Name | Size (bytes) | Pages | Cached | Percent | |-------+----------------+------------+-----------+---------| | file | 536870912 | 131072 | 131072 | 100.000 | +-------+----------------+------------+-----------+---------+ 從 pcstat 的結果你可以發現,測試文件 file 已經被全部緩存了起來,這跟剛才觀察到的緩存命中率 100% 是一致的。 這兩次結果說明,系統緩存對第二次 dd 操作有明顯的加速效果,可以大大提高文件讀取的性能。 但同時也要注意,如果我們把 dd 當成測試文件系統性能的工具,由于緩存的存在,就會導致測試結果嚴重失真。案例二
接下來,我們再來看一個文件讀寫的案例。這個案例類似于前面學過的不可中斷狀態進程的例子。它的基本功能比較簡單,也就是每秒從磁盤分區 /dev/sda1 中讀取 32MB 的數據,并打印出讀取數據花費的時間。 為了方便你運行案例,我把它打包成了一個 Docker 鏡像。 跟前面案例類似,我提供了下面兩個選項,你可以根據系統配置,自行調整磁盤分區的路徑以及 I/O 的大小。- -d 選項,設置要讀取的磁盤或分區路徑,默認是查找前綴為 /dev/sd 或者 /dev/xvd 的磁盤。
- -s 選項,設置每次讀取的數據量大小,單位為字節,默認為 33554432(也就是 32MB)。
總結
Buffers 和 Cache 可以極大提升系統的 I/O 性能。通常,我們用緩存命中率,來衡量緩存的使用效率。命中率越高,表示緩存被利用得越充分,應用程序的性能也就越好。 你可以用 cachestat 和 cachetop 這兩個工具,觀察系統和進程的緩存命中情況。其中,- cachestat 提供了整個系統緩存的讀寫命中情況。
- cachetop 提供了每個進程的緩存命中情況。
總結
以上是生活随笔為你收集整理的17 | 案例篇:如何利用系统缓存优化程序的运行效率?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 16 | 基础篇:怎么理解内存中的Buf
- 下一篇: java信息管理系统总结_java实现科