名前でファイルを削除するのが非常に遅く、非常に速いのはなぜですか?


11

Faux pas:私が以下に述べる「速い」方法は遅い方法より60倍速くはありません。30倍高速です。私は時間の間違いを非難します(午前3時は明確な思考のための私の最高の時間ではありません:)。

更新:テスト時間の要約を追加しました(下記)。
速度係数には2つの問題があるようです。

  • 使用するコマンドの選択(以下の時間比較)
  • ディレクトリ内の多数のファイルの性質...「大きいことは悪いこと」のようです。数値が増加するにつれて、物事は不均衡に遅くなります。

すべてのテストは100万のファイルで行われました。
(実時間、ユーザー時間、sys時間はテストスクリプトに含まれています)
テストスクリプトは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
#                                                       

最近、1,000万の空のテストファイルを作成して削除しました。名前ごとにファイルを削除すると(つまりrm filename)、2つの異なる方法の間に大きな時間差があるという難しい方法がわかりました...

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

更新:結局のところ、コマンドはまったく同じではありません...それらの1つは一度に1000個のファイル名を 'rm'に送信していました...それは、各ファイル名が書き込まれていると思ったシェルブレース展開の問題でしたそれ自体の行でフィーダーファイルに追加されましたが、実際には1行あたり1000でした。

filnamesは 'フィーダーファイル'を介してwhile readループに提供されます。
フィーダーファイルは次の出力ですls -1 -f
メソッドは、1つの点を除いて、すべての点で同じです。

  • 遅い方法はからの直接ソートされていないフィーダファイルを使用していますls -1 -f
  • 高速な方法は、同じソートされていないファイルのソートされたバージョンを使用しています

ここでソートが問題であるかどうか、またはソートされたフィーダーファイルがファイルが作成された順序と偶然一致しているのかどうかはわかりません(私は単純な昇順整数アルゴリズムを使用しました)

100万ファイルの場合、高速 rm filenameメソッドは低速メソッドより60倍高速です...繰り返しますが、これが「ソート」の問題なのか、舞台裏のハッシュテーブルの問題なのかはわかりません...これは単純な並べ替えの問題ではありません。なぜ新しく追加された「並べ替えられた」ファイル名のシーケンスの並べ替えられていないリストが意図的に与えられるのですか... ls -1 -f

私はここで何が起こっているのだろうと思っているので、次の1000万のファイルを削除するのに何日も(はい数日)かかりません:) ....私は「日」と言います。倍の関与のnumberOfファイルへdisproportionatly関与増加..私はのみテストしてみたので、1詳しく万人を

ところで:名前の「ソートされたリスト」を介してファイルを削除しても、実際にはより高速であるrm -rf2倍
と:rm -r30倍遅く、「ソートされたリスト」方式を超えました

...しかし、ここで問題を「分類」していますか?それとも、ext4が使用するストレージのハッシング(またはその他の)メソッドにもっと関連していますか?

私をかなり困惑させることは、それぞれの呼び出しがrm filename前の呼び出しと無関係であることです。(まあ、少なくとも「bash」の観点からはそうです)

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


1
あなたはそれを間違っています!(tm)聞いたことがありfind -deleteますか?
アレックス

2つのテストは、等しくない条件で開始します(これが実際に重要であるとは思いません)。1つはファイルからファイル名を読み取り、もう1つはテストの直前に作成(ソート)されたファイルからファイル名を読み取ります。2番目のケースでキャッシュされているファイルが一部を再生する(または、おそらく再生しない)場合があります。テストをより均等な状態にcatするためsortに、2番目のテストの前ではなく、1番目のテストの前に、単純なファイルから新しいファイルを作成する必要があります。
imz-Ivan Zakharyaschev

そして、あなたの観察とあなたの質問をより明確な方法で提示することをお勧めします。一度に1つずつお願いします。1つの質問で2つのケースのみを比較し、重要な2つのケースを前面に出してください。他のすべてのケースは背景情報です。これを明確にしてください。1つの投稿に複数の観察結果を混在させないでください。
imz-Ivan Zakharyaschev 2011年

パズルを解くには、システムとユーザー空間の時間を提示することも重要かもしれないので、質問に含めてください。それらのうちどれがあなたのテストに大きな違いをもたらしますか?
imz-Ivan Zakharyaschev 2011年

1
時期尚早の最適化は、すべての悪の根源です。:)いつ1000万のファイルを削除しますか?1秒あたり100 000は、(システムを破壊するために)十分に高速に思えます。
ユーザー不明

回答:


2

rm -rは再帰的であるため、低速であると予想されます。深さ優先トラバーサルは、ディレクトリ構造で行う必要があります。

では、1,000万のファイルをどのように作成しましたか?ある順序でループするスクリプトを使用しましたか?1.txt、2.txt、3.txt ...はいの場合、それらのファイルは、hdd.so内の隣接するブロックに同じ順序で割り当てられている可能性があるため、同じ順序で削除すると高速になります。

"ls -f"を指定すると-aUが有効になり、ディレクトリの順序でリストが再帰的に表示されます。


1
マカロット:この場合、サブディレクトリが含まれていないため、「再帰」がどのように重要であるかわかりません...はい、「1.txt、2.txt、3.txt」を使用しました。おそらくいくつかあります相互作用するもの:たとえば、100万個のファイルを作成するのに1分30秒しかかかりませんが、200万個を作成するのに7分10秒かかります。それらを削除した後、100万個を再作成するのにはかなり時間がかかります(9分30秒)。ゆっくりと突然、これも以前に起こりました。ディレクトリを削除することで修正されたと思います(?)ファイルデーモン(nautilus、locate)が含まれている可能性がありますか?続行するには...
Peter.O

一般に、ファイルシステムは、同じディレクトリ内の多数のファイルを処理するように最適化されていません。特にext4については詳しくありませんが、他の形式では、ファイルが削除されたときにディレクトリエントリが未使用としてマークされていました。つまり、ディレクトリで操作を行う場合は、スキップする必要があります。それはあなたが見ている行動を説明するでしょう。
KeithB 2011年

1
「今より遅い」ディレクトリを削除し、新しいディレクトリに別の名前を使用しました。100万個のファイルを作成する時間は1分33秒に戻ります(ディレクトリに200万個の削除されたファイルが「含まれる」場合は9分30秒。最初の100万個は新しく追加された100万と同じ名前です)...そして興味深いあなたの"...未使用としてマークされた"コメントを集計します...そこに着きます。それは理にかなっています:)
Peter.O

@ fred.bear私の悪いことに、私は実際の階層を本当に知りませんでした、そして私の答えは推測でした。また、テストは実際にはメタデータに負荷をかけますが、実際のファイルは空のファイルであるため、そうではありません。この種の問題をベンチマークする最良の方法は、/ varまたはWebサーバーのキャッシュからファイルを取得することです。とにかく、あなたのテストがあまりにもintrestingの音、あなたは... /sample1/1.txt,2.txt ...と/sample2/1.txt,2.txtなどの異なるdirectories..sayに2つの列挙された方法で削除してみてくださいすることができます
rajaganesh87

@ Mr.Confused.A.Lot ...助けてくれてありがとう あなたの説明は私がファイルシステムとその方法論のいくつかについてもっと理解するのに役立ちました...私は今、さまざまな速度の問題を引き起こしているものの合理的な意味を理解しました...新しいモットーを残しました:ディレクトリの「大きな問題」(少なくともいくつかのアクションでは)...
Peter.O

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

もちろん、これはすべてハッシュテーブルから概念をだらしなく借りている


「もっと小さなディレクトリを使う」と言っていると思います...それは興味深いアイデアです。「ツリーのない」ファイルグループからツリーを作成する自社開発のDBMS」。フォワードプランと呼ぶ人もいます:) ...機能する場合(そして機能する場合)、それは良いアイデアです!:) ...私は「ディレクトリが(ext4については)少なくともファイル内のファイル数になると、「大きいのは悪い」という考えを持ち始めています...先制的な回避策(+1)を提示しました。 Mゆっくり一部の削除方法は速く、任意のディレクトリに他のものよりである理由のアイデアを取得し、小規模または大規模な...おかげで
Peter.O

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.