findは深度優先検索を実行する方法なので、常にアルファベット順にファイルを一覧表示します。これらの制限を軽減する意図がある場合は、検索の並列性を向上させるか、他の同様のツールを使用して空のファイルを見つけることができますか? (他の同様の基準を使用してファイルを見つける戦略も気になりますがfind
、具体性のために空のファイルを使用します)。
だから私は私のホームディレクトリにあるすべての空のファイルを任意の順序で見つけようとしています。
OS Xでは、bashを使用して次のコマンドを実行します。
$ find . -type f -empty >& /dev/null
real 0m10.334s
user 0m0.525s
sys 0m5.568s
並列性を向上させるために私が考えることができる最も簡単な方法を使用し、Perlスクリプトを使用してディレクトリ固有の検索を呼び出しました。 Perlスクリプトは、find
独自のプロセスの各最上位ディレクトリまたはファイルでのみ実行されます。
このスクリプトの総実行時間は、単一の照会の半分よりわずかに短いです。
#!/usr/bin/env perl
use strict;
use warnings;
opendir(my $fh, '.');
while (readdir($fh)) {
my $item = $_;
next if $item eq '.';
next if $item eq '..';
my $cpid = fork();
if ($cpid == -1) {
die;
} elsif ($cpid == 0) {
exec 'find', "./$item", '-type', 'f', '-empty', or die;
}
}
while (wait() != -1) {}
例えば
$ time perl find-parallel.pl >& /dev/null
real 0m4.245s
user 0m1.126s
sys 0m8.281s
find
ある種のスクリプトを使用してある程度の深さでスタンドアロンを手動で実行することは、この問題を解決するためのやや不器用な方法のようです。もっと良い方法がありますか?
答え1
まず、小さな問題があります。少なくともLinuxでは、findの出力順序はアルファベット順ではありません。代わりに、ディレクトリインデックスの順序(通常は生成順序)です。
exec
それ自体(syscallまでexecve
)は、作業中の規模でかなりのオーバーヘッドを持っているので、これを避けることをお勧めします。
ソリューションの一般的なフレームワークとして、少なくとも2つのスレッドベースが必要です。
- キュー・マネージャー
- 労働者)
論理:
- キューは単一のディレクトリから始まります
.
。 - キューで何かが使用可能で、まだ並列スレッドの制限に達していない場合は、キューのエントリでワーカースレッドを起動します。
- ワーカー:指定されたディレクトリを非再帰的に読み込みます。
- 確認済みの新しいディレクトリの場合は、そのディレクトリをキューに追加します。
- 他の新しいファイルは正常に処理されます。
特別な状況に対処する必要があります。
- 同じ項目を指す複数のシンボリックリンク。
- 他のディレクトリへのシンボリックリンク。
- より高いレベルのシンボリックリンクをたどると繰り返されます。
これは非並列ルックアップよりもパフォーマンスが良いですか?これは難しい質問であり、使用されるファイルシステム/カーネルによって異なります。
たとえば、事前に構築されたソリューションを探している場合は、Go Parallel Directory Walkerを探してください。ただし、次の費用に注意してください。追加stat
通貨。
答え2
これは私がC ++で書いたGithubの無料のLinux並列検索ツールです。 https://github.com/breuner/elfindo
次のようにして空のファイルを見つけることができます。
$ elfindo . -type f -size 0
パラメータを使用して明示的にスレッド数を設定できます-threads
。
$ elfindo . -type f -size 0 -threads 32