Bash

為什麼按名稱刪除文件非常慢而且速度非常快?

  • March 22, 2011

錯誤:我在下面提到的“快速”方法並不比慢速方法快 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 -rf2 倍。

並且: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

當然,這都是從雜湊表中草率地借用概念

引用自:https://unix.stackexchange.com/questions/9798