2018年12月3日 星期一

手動清除 Linux 記憶體快取

Source: https://medium.com/hungys-blog/clear-linux-memory-cache-manually-90bec95ea003

在跑碩論實驗時曾經遇過一個詭異的問題,實驗的 script 連續跑了五次 gzip 壓縮的 workload 要進行效能 benchmark,但跑出來的結果第一次的執行時間與第二到第五次的執行時間有很明顯的落差,於是開始懷疑是記憶體快取所造成的問題。
Linux 中提供了 free 指令可以觀察系統中記憶體的使用情況,而觀察後發現跑完一次 gzip 後被快取的記憶體多了將近 800MB,這正好是 input 測資的大小,而這些 cache 並不會隨著 process 的結束而馬上被清理掉。
$ free
              total        used        free      shared  buff/cache   available
Mem:       16318560      116200    16097624       20904      104736    15958096
Swap:      16662524       22088    16640436
$ ./gzip_compress_benchmark.sh
$ free
              total        used        free      shared  buff/cache   available
Mem:       16318560      117596    15329324       20904      871640    15889304
Swap:      16662524       22088    16640436
一般來說使用者是不需要去管這些 cache 何時會被清除的,所以 Linux 也沒有專門的指令來做這件事,不過依然有提供一個 proc file system 介面 /proc/sys/vm/drop_caches 可以強制 kernel 清理快取。若有這樣的需求,我們只需要對這個 file 寫入 1~3 這三種控制碼其中一種,對應的記憶體快取種類便會被強制清理。
若寫入 1 會清除 pagecache:
# echo 1 > /proc/sys/vm/drop_caches
若寫入 2 會清除 dentries 與 inodes:
# echo 2 > /proc/sys/vm/drop_caches
若寫入 3 則有等同於 1+2 的效果,會清除 pagecache、dentries 及 inodes:
# echo 3 > /proc/sys/vm/drop_caches
要寫入這個 file 必須有 root 權限,所以非 root 帳號需要使用 sudo 來執行:
$ sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches'
$ sudo sh -c 'echo 2 > /proc/sys/vm/drop_caches'
$ sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
基本上執行這個指令沒有什麼好處,所以除非你很明確知道你想幹嘛(例如這邊是為了避免 cache 影響實驗結果),否則建議不要隨便手動清除快取記憶體。另外,也建議在做這個動作前先執行 sync 讓檔案寫入操作先完成,否則可能會造成意想不到的結果。
另外,雖然 /proc/sys/vm/drop_caches 預設的值是 0,但做完以上動作其實也沒有一定需要再寫回 0,主要是因為 kernel 只有在 proc file system 的 handler 觸發時才會做對應的清理工作,並不是持續或定期看這個數值來清理的。
這個問題其實當初在 local 的 VM 環境並沒有遇到,所以在 server 跑實驗時發生覺得滿詭異的,但後來想想 local VM 只配置了 1GB 的記憶體,每次跑 gzip 時並非檔案的所有內容都還保留在記憶體裡,所以會有這樣的差別算滿合理的。

沒有留言: