名前でファイルを削除するのは痛いほど遅いですが、とても速いのはなぜですか?

名前でファイルを削除するのは痛いほど遅いですが、とても速いのはなぜですか?

失礼:以下の「高速」方法は、遅い方法よりも60倍速くはありません。 30倍速くなりました。私はこの間違いをその時に責める。 (午前3時は私が明確に考えるのに最適な時間ではありません:)..

更新:テスト時間の概要を追加しました(下)。
速度要素には2つの問題が関係しているようです。

  • 使用されるコマンドの選択(下記のタイミング比較を参照)
  • ディレクトリに多数のファイルがあるという特性は…「大きなものは悪いもの」のように見えます。数が増加すると、状況は不均衡に遅くなります。

すべてのテストは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
#                                                       

最近作成して削除しました。1010,000個の空のテストファイル。名前(例rm filename:)でファイルを削除するには巨大な2つの方法の時間差...

どちらの方法もまったく同じrm filenameコマンドを使用します。

更新:このコマンドはまったく同じではないことがわかりました...そのうちの1つは、「rm」として一度に1000個のファイル名を送信しています...シェル支柱拡張の問題です。各ファイル名がフィーダファイルに書き込まれるようです。 1行がありますが、実際には1行に1000本あります。

ファイル名はwhile read「フィードファイル」を介してループに渡されます。
フィードファイルはこれらのメソッドの出力であり、次のいずれls -1 -f
かを除いてすべての点で同じです。

  • これ遅いソートされていないフィーダーファイルを直接使用する方法ls -1 -f
  • これ早くメソッドは、ソートされていない同じファイルのソートされたバージョンを使用します。

ここでは、ソートが問題なのか、ソートされたフィードファイルがファイルが生成された順序と一致するのかわかりません(単純な昇順整数アルゴリズムを使用しました)。

100万個のファイルについて、早く rm filename方法は60比較する遅い方法... 繰り返しますが、これが「ソート」の問題なのか、背後のハッシュテーブルの問題なのかはわかりません...単純なソートの問題ではないようです。なぜ意図的にls -1 -f私にソート解除新しく追加された「ソートされた」ファイル名シーケンスのリスト...

次の1000万ファイルを削除するのに数日(例えば数日)がかかるのを防ぐために、ここで何が起こっているのかを知りたいです。 :) ....多くの選択肢を試したので、「仕事」と言います。関連ファイルの数に応じて、関連項目が不均衡に増加します。それでテストだけしました。1何千もの詳細

注:名前の「ソートされたリスト」でファイルを削除することは、実際にはrm -rf「ソートされたリスト」方法よりも2倍高速です。
AND:rm -r「ソートされたリスト」アプローチより30倍遅い

…しかし、ここで質問は「ソート」されていますか?それとも、ext4で使用されるハッシュ(または他の)保存方法ともっと関連がありますか?

私を混乱させることは、各呼び出しが以前の呼び出しrm filenameとは何の関係もないということです。 (少なくとも「bash」の観点から)

私はUbuntu/bash/'ext4'/SATA IIドライブを使用しています。

答え1

rm -r は再帰のために遅くなると予想されます。ディレクトリ構造の深さ優先探索を実行する必要があります。

それでは、1000万個のファイルをどのように生成しますか?どのような順序で繰り返されるスクリプトを使用していますか? 1.txt,2.txt,3.txt... もしそうなら、これらのファイルは同じ順序でHDDの連続したブロックに割り当てられます。したがって、同じ順序で削除する方が高速です。

"ls -f"は-aUを有効にします。これは再帰的なディレクトリの順序でリストされます。

答え2

ファイル構造を最適化する必要があります。だから代わりに

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

もちろん、これはすべてハッシュテーブルの概念を急いで借りたものです。

関連情報