為什麼按名稱刪除文件非常慢而且速度非常快?
錯誤:我在下面提到的“快速”方法並不比慢速方法快 60 倍。它快 30 倍。我會把錯誤歸咎於時間(凌晨 3 點不是我一天中清晰思考的最佳時間:)..
更新:我添加了測試時間的摘要(如下)。
速度因素似乎涉及兩個問題:
- 所用命令的選擇(時間比較如下圖)
- 目錄中大量文件的性質……似乎“大就是壞”。隨著數字的增加,事情變得不成比例地變慢。
所有測試均使用 100 萬個文件完成。
(真實、使用者和系統時間在測試腳本中)
測試腳本可以在paste.ubuntu.com找到
# # 1 million files # =============== # # |time |new dir |Files added in ASCENDING order # +---- +------- +------------------------------------------------- # real 01m 33s Add files only (ASCENDING order) ...just for ref. # real 02m 04s Add files, and make 'rm' source (ASCENDING order) # Add files, and make 'rm' source (DESCENDING order) # real 00m 01s Count of filenames # real 00m 01s List of filenames, one per line # ---- ------- ------ # real 01m 34s 'rm -rf dir' # real 01m 33s 'rm filename' via rm1000filesPerCall (1000 files per 'rm' call) # real 01m 40s 'rm filename' via ASCENDING algorithm (1000 files per 'rm' call) # real 01m 46s 'rm filename' via DESCENDING algorithm (1000 files per 'rm' call) # real 21m 14s 'rm -r dir' # real 21m 27s 'find dir -name "hello*" -print0 | xargs -0 -n 1000 rm' # real 21m 56s 'find dir -name "hello*" -delete' # real 23m 09s 'find dir -name "hello*" -print0 | xargs -0 -P 0 rm' # real 39m 44s 'rm filename' (one file per rm call) ASCENDING # real 47m 26s 'rm filename' (one file per rm call) UNSORTED #
我最近創建並刪除了1000萬個空測試文件。按名稱刪除文件(即
rm filename
),我發現兩種不同方法之間存在巨大時間差異的困難方式……兩種方法都使用完全相同的
rm filename
命令。更新:事實證明,這些命令並不完全相同……其中一個是一次向“rm”發送 1000 個文件名……這是一個 shell 大括號擴展問題,我認為每個文件名都被寫入到饋線文件的一行,但實際上是每行 1000
文件名是通過“饋線文件”提供到
while read
循環中的。饋線文件是的輸出
ls -1 -f
方法在所有方面都是相同的,除了一件事:
- 慢速方法直接使用未排序的饋線文件
ls -1 -f
- 快速方法使用同一未排序文件的排序版本
我不確定排序是否是這裡的問題,或者排序的饋線文件是否恰好與創建文件的順序匹配(我使用了一個簡單的升序整數算法)
對於 100 萬個文件,快速
rm filename
方法比慢速方法快60倍……再說一遍,我不知道這是“排序”問題,還是幕後雜湊表問題……我懷疑這不是一個簡單的排序問題,因為為什麼會故意給我一個新添加的“排序”文件名序列的未排序列表 ……ls -1 -f
我只是想知道這裡發生了什麼,所以我不需要幾天(是幾天)來刪除接下來的 1000 萬個文件:) …. 我說“幾天”是因為我嘗試了很多替代方案,而且所涉及的時間與所涉及的文件數量不成比例地增加..所以我只詳細測試了100萬個
順便說一句:通過名稱的“排序列表”刪除文件實際上比“排序列表”方法快
rm -rf
2 倍。並且:
rm -r
比“排序列表”方法慢 30 倍…但是這裡的問題是“排序”的嗎?還是與 ext4 使用的散列(或其他)儲存方法更相關?
令我困惑的是,每次呼叫
rm filename
都與前一次無關..(嗯,至少從“bash”的角度來看是這樣)我正在使用 Ubuntu / bash / ’ext4’ / SATA II 驅動器。
rm -r 預計會很慢,因為它是遞歸的。必須對目錄結構進行深度優先遍歷。
現在你是如何創建 1000 萬個文件的?您是否使用了一些按順序循環的腳本?1.txt,2.txt,3.txt…如果是,那麼這些文件也可能以相同順序分配在 hdd 中的連續塊中。因此以相同順序刪除會更快。
“ls -f”將啟用 -aU,它按目錄順序列出,這又是遞歸的。
您應該優化文件結構。所以而不是
for i in $(seq 1 1000); do touch file.$i; done
做一些更聰明的事情(假設 bash):
function bucklocate() { hash=$(echo -n "$1"|md5sum|cut -f1); echo -n "${hash:1:1}/${hash:7:1}/${hash:9:2}/$1"; } hexdig="{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}" eval mkdir -p $hexdig/$hexdig/$hexdig$hexdig for i in $(seq 1 1000); do touch $(bucklocate file.$i); done
現在這個例子由於使用了 md5sum 而變得相當慢
$$ 1 $$,使用類似下面的東西來更快的響應,只要你不需要任何特定的文件名,重複是沒有關係的,也不需要某個名稱的可重複雜湊:)
mkdir -pv {0,1,2,3,4,5,6}/{0,1,2,3,4,5,6,7,8,9,10,12} for a in $(seq 1 100); do i=$RANDOM; echo touch "$(($i%7))/$(($i%13))/file.$i"; done
當然,這都是從雜湊表中草率地借用概念