- 上一篇 Linux系統緩存知識整理 中提到幾個測試用例,這裏補充一下詳細的測試數據和結論。
LRU緩存回收策略的驗證
環境信息:
[root~]# uname -r
2.6.32-431.el6.x86_64
[root~]# cat /etc/redhat-release
CentOS release 6.5 (Final)
[root~]# free -g
total used free shared buffers cached
Mem: 62 10 52 0 0 2
-/+ buffers/cache: 7 55
Swap: 31 0 31
準備工作:
- 構造兩個32GB大小的文本文件(即:讓文件大小超過緩存最大大小的一半)
- 這個用例主要是驗證網上講到的一個問題: 使用大數據時,別忘了關注Linux內存管理器
[root]# ls -lhtr
total 64G
-rw-r--r-- 1 root root 32G May 3 14:36 file1.csv
-rw-r--r-- 1 root root 32G May 3 14:45 file2.csv
操作步驟:
第一組測試
- 先多次執行time wc -l file1.csv,觀察每次執行所用時間
- 在不清理緩存情況下,多次執行time wc -l file2.csv,觀察每次執行所用時間。
- 同時使用linux-fincore工具查看file1和file2這兩個文件的cache情況(關於這個工具也請參考上一篇博文的介紹)
測試數據:
- 先多次(大約六七次) wc -l file1.csv, 可以看到file1.csv被完全cache住:
# 第一次執行耗時5分鐘多
[root]# time wc -l file1.csv
107746446 file1.csv
real 5m8.501s
user 0m5.280s
sys 0m16.962s
# 第二次執行只用了22秒
[root]# time wc -l file1.csv
107746446 file1.csv
real 0m22.138s
user 0m2.133s
sys 0m8.252s
# 第三次執行只用了9秒,且之後都是9秒左右。
[root@192-168-19-124 cache_test]# time wc -l file1.csv
107746446 file1.csv
real 0m9.550s
user 0m2.168s
sys 0m6.785s
# 第三次執行之後,查看file1的緩存情況:
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 0 8,250,070 33,792,286,720 100.00
---
total cached size: 33,792,286,720
- 不清理緩存,直接執行
wc -l file2.csv
。同樣耗時5分多。但通過fincore查看,直到命令被執行完、且通過free看到系統內存幾乎耗盡,file2被cache的大小也只佔到 33.8%,而file1.csv仍然被cache 98.7%
[root]# time wc -l file2.csv
102468691 file2.csv
real 5m23.170s
user 0m4.718s
sys 0m20.965s
[root]# free -g Fri May 4 15:11:54 2018
total used free shared buffers cached
Mem: 62 60 2 0 0 45
-/+ buffers/cache: 15 47
Swap: 31 0 31
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 106,991 8,143,079 33,354,051,584 98.70
/home/cache_test/file2.csv 34,073,762,786 8,318,790 1,786,282 2,811,795 11,517,112,320 33.80
---
total cached size: 44,871,163,904
- 第二次執行
wc -l file2.csv
,仍然耗時5分鐘多,比第一次略快,完畢後可以看到file1的cache減少,file2的cache增加。
[root]# time wc -l file2.csv
102468691 file2.csv
real 5m19.290s
user 0m4.718s
sys 0m20.965s
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 1,226,576 6,611,513 27,080,757,248 80.14
/home/cache_test/file2.csv 34,073,762,786 8,318,790 1,052,496 4,326,571 17,721,634,816 52.01
---
total cached size: 44,802,392,064
- 第三次執行
wc -l file2.csv
[root]# time wc -l file2.csv
102468691 file2.csv
real 4m18.372s
user 0m4.540s
sys 0m19.338s
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 1,226,576 5,457,623 22,354,423,808 66.15
/home/cache_test/file2.csv 34,073,762,786 8,318,790 0 5,257,364 21,534,162,944 63.20
---
total cached size: 43,888,586,752
- 大約六七次執行之後,可以看到file2已經完全在cache中。之後再次執行
wc -l file2.csv
速度就很快了
[root]# time wc -l file2.csv
102468691 file2.csv
real 1m56.612s
user 0m2.953s
sys 0m13.424s
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 1,226,576 2,328,421 9,537,212,416 28.22
/home/cache_test/file2.csv 34,073,762,786 8,318,790 0 8,318,790 34,073,763,840 100.00
---
total cached size: 43,610,976,256
[root]# time wc -l file2.csv
102468691 file2.csv
real 0m8.339s
user 0m2.002s
sys 0m6.336s
第二組測試
- 爲了驗證file1訪問次數和後面file1的cache被淘汰速度之間的關係,我們執行
echo 3 > /proc/sys/vm/drop_caches
清理所有緩存後,重新做一次測試。 初始狀態僅執行一次wc -l file1.csv
,將file1完全加載到緩存。
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 35,544 8,214,526 33,646,698,496 99.57
---
total cached size: 33,646,698,496
- 然後執行一次
wc -l file2.csv
,可以看到file2已經被100% cache,而file1大部分內容已被逐出緩存。
[root]# ./linux-fincore --pages=false --summarize --only-cached /home/cache_test/*
filename size total_pages min_cached page cached_pages cached_size cached_perc
-------- ---- ----------- --------------- ------------ ----------- -----------
/home/cache_test/file1.csv 33,792,286,436 8,250,070 3,286,806 4,298,896 17,608,278,016 52.11
/home/cache_test/file2.csv 34,073,762,786 8,318,790 0 8,318,790 34,073,763,840 100.00
---
total cached size: 51,682,041,856
結論
- 第一組測試與網上提到的修復方案描述一致: 即系統會記錄file2對應頁面的累積訪問次數,儘管file1佔據active緩存隊列時,file2只能在inactive中,且由於無法全部加載到內存,file2加載到尾部時其頭部的緩存頁面已經被淘汰。但作爲修復方案,系統仍然會記錄其最近訪問計數,並在計數達到一定次數後將其移動到active隊列,並逐出file1對應的緩存頁面。
- 需要注意這與我們普通理解的LRU仍然有一些不同:並非file2被訪問一次之後就完全被cache住!!!事實上,第一次訪問後,file2僅有一小部分在cache2中,隨着其訪問次數的增加,在逐漸將file1逐出cache。
- 第二組測試中,由於file1最初僅被訪問一次,所以這和我們理解的LRU是一樣的:file2訪問一次之後就完全被cache,file1的大部分內容被從緩存中逐出,以給file2“騰”出空間。
/proc/sys/vm/drop_caches
取值1和2的區別
echo 1 > /proc/sys/vm/drop_caches
是清理數據緩存。例如上面的例子中,echo
1 和 echo 3 效果基本差不多,因爲主要是數據緩存,元數據很少。echo 2 > /proc/sys/vm/drop_caches
是清理目錄和inode緩存。在目錄、文件數量很多情況下,可以使用這個命令。
測試驗證
準備條件
- 創建一個/home/test目錄,在test目錄下創建約3.2萬個子目錄,每個子目錄下100個文件。即總共約320萬個文件
操作步驟
- 執行find命令查找test目錄下所有文件,第一次執行耗時5分多,之後由於緩存,只需要10秒以內。
# 第一次執行
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 5m30.465s
user 0m11.033s
sys 0m34.133s
# 第二次執行
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 0m18.615s
user 0m2.489s
sys 0m5.287s
# 第三次執行
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 0m3.374s
user 0m1.421s
sys 0m1.930s
- 執行
echo 1 > /proc/sys/vm/drop_caches
之後再次執行find命令,速度仍然很快。可見目錄和文件inode緩存仍在。
[root@localhost home]# echo 1 > /proc/sys/vm/drop_caches
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 0m3.554s
user 0m1.424s
sys 0m1.949s
- 執行
echo 2 > /proc/sys/vm/drop_caches
之後再次執行find命令,速度很慢。可見 緩存已經被清理掉了。但再次執行,由於前面已經緩存過,速度又變快。
[root@localhost home]# echo 2 > /proc/sys/vm/drop_caches
# 由於緩存被清理,這次執行耗時8分鐘多
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 8m22.344s
user 0m11.845s
sys 0m51.035s
# 再次執行,又有了緩存,速度很快
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 0m3.375s
user 0m1.361s
sys 0m1.913s
- 執行
echo 3 > /proc/sys/vm/drop_caches
之後在測試,針對這個場景,效果和echo 2 一樣:
[root@localhost home]# echo 3 > /proc/sys/vm/drop_caches
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 8m22.845s
user 0m11.121s
sys 0m49.958s
[root@localhost home]# time find /home/cache_test -name file* | wc -l
3125400
real 0m3.294s
user 0m1.422s
sys 0m1.852s
總結
- 通過上面這些例子,
echo 1 > /proc/sys/vm/drop_caches
和echo 2 > /proc/sys/vm/drop_caches
的區別已經很清晰了。