グラフィカルなファイル検索ユーティリティと比較して、GNUが非常に高速に検索されるのはなぜですか?


47

ホームディレクトリとすべてのサブディレクトリに存在しないファイルを見つけようとしています。

find ~/ -name "bogus"数秒後にその情報が提供されますが、KDEのdolphinファイルマネージャーは同じことを行うのに約3分かかりました。これは、以前のGNOMEでのbeagle経験に対応しています。

findグラフィカルな検索(コマンドラインパラメーターよりも直感的に使用できます)が遅れている間、どのようにして同じように非常に高速に処理できますか?


「Dolphin」とは何なのかわかりませんが、ファイルの内部も見えるのでしょうか?
クサラナナンダ

1
KDEのグラフィカルファイルマネージャです。kde.org / applications / system / dolphinファイル内を検索する機能がありますが、この短いテストではそのオプションを有効にしませんでした。

9
イルカで複数回検索しましたか?初めての「インデックス作成」の可能性があります。「検索」も遅いです。ロケート用のデータベースに最後にインデックスが作成されたときよりもファイルが古い場合は、「ロケート」を試してください;-)
Rinzwind

私はlocateより頻繁に使用findし、巨大なフォルダで高速です
-phuclv

11
一方、locateファイルを見つけるための本当に素晴らしいです、それは完全に異なるアプローチを使用しているため、これは、ビットOTですfindとGUIツールが好きDolphinながら、オンデマンドでファイルツリーをトラバースしているlocate以前に作成したインデックス構造を使用しています。
マイケルシェーファーズ

回答:


68

BalooでDolphinを具体的に見ると、単純なファイル名検索を実行している場合でも、検索ドメイン内のすべてのファイルのメタデータを検索するようです。私がトレースするときfile.soのプロセスを、私はへの呼び出しを参照lstatgetxattrgetxattr再びすべてのファイルのため、さらにはのため..のエントリを。これらのシステムコールは、ファイル名とは異なる場所に保存されているファイルに関するメタデータを取得します(ファイル名はディレクトリの内容に保存されますが、メタデータはinodeに保存されます)。データがディスクキャッシュにあるため、ファイルのメタデータを複数回クエリするのは安価ですが、メタデータをクエリする場合とメタデータをクエリしない場合には大きな違いがあります。

findはるかに賢いです。不要なシステムコールを回避しようとします。getxattr拡張属性に基づいて検索しないため、呼び出しません。ディレクトリを横断するとき、それはlstat再帰的に検索するサブディレクトリである可能性があるため、一致しないファイル名を呼び出す必要があります(lstatregular / directory / symlink / ...などのファイルタイプを含むファイルメタデータを返すシステムコールです)。ただしfind、最適化があります。リンクカウントからディレクトリのサブディレクトリ数をlstat認識し、すべてのサブディレクトリを横断したことがわかると、呼び出しを停止します。特に、リーフディレクトリ(サブディレクトリのないディレクトリ)では、findメタデータではなく、名前のみをチェックします。さらに、一部のファイルシステムは、ディレクトリエントリにファイルタイプのコピーを保持しているため、find必要なlstat情報がそれだけである場合は呼び出す必要さえありません。

findメタデータの確認を必要とするオプションを使用して実行すると、さらにlstat呼び出しがlstat行われますが、情報が必要ない場合はファイルに対して呼び出しを行いません(たとえば、ファイルが前の条件によって除外されているため)名前の一致)。

find車輪を再発明する他のGUI検索ツールは、数十年にわたって最適化されてきたコマンドラインユーティリティよりも賢くないと思われます。Dolphinは、少なくとも、「どこでも」を検索する場合に検索データベースを使用するのに十分賢いです(UIで結果が古くなっている可能性があるという明確な制限はありません)。


22
GNU findは非常に「賢い」ため、一部のファイルシステムタイプの一部のファイルを見逃しています。GNU findでよく知られているバグは、ディレクトリのリンクカウントが次のように違法であると仮定していること2 + number of sub-directories.です。 。GNU makeの有用なパフォーマンス番号を取得したい場合は、GNU make -noleafが正しく動作するように指示するために指定する必要があります。
18年

12
@ schily、GNU findはずっと前にそのバグを抱えていたかもしれませんが、-noleaf最近手作業で指定する必要があるケースを見つけることを疑います。AFAICT、少なくともLinux上getdents()(およびreaddir())では、どのファイルがUDF、ISO-9660、btrfs上のディレクトリファイルであり、実際.または..エントリを持たず、findそこで動作するかがわかります。GNU findが問題を示す1つのケースを知っていますか?
ステファンシャゼラス

4
debianのこの腐ったgenisoimageを使用して、「graft-points」を使用してRock Ridgeファイルシステムを作成します。ディレクトリ内のリンクカウントはランダムな値です。Rock Ridgeはリンクカウントと./ ..を実装しているため、GNU findは通常、そのようなファイルシステム上のすべてのファイルを検索しません。
18年

4
@StéphaneChazelas:前回(修士論文)をチェックしたとき、バグは<= 2ではなく正確に2を意味する既知の葉をアサートすることで修正されました。2+カウンターを実装していないファイルシステムは、すべて良し。ある日、誰かがこのプロパティを持たないディレクトリへのハードリンクを行うファイルシステムを作成した場合、誰かが悪い日を過ごすことになります。
ジョシュア

15
@ schily、Debian上のgenisoimage 1.1.11でグラフトポイントとRRでランダムなリンクカウントを取得できませんでした。リンクカウントをランダムな値に変更するためにisoイメージをバイナリ編集しても、まだ表示されませんGNUの問題find。そして、いずれの場合でも、ディレクトリに対してd_type = DT_DIRを正しく返すstrace -vことgetdents()を示しているため、GNU findはリンクカウントトリックを使用する必要がありません。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.