多数のファイルに対応する、ファイルのハード リンク カウントを取得するより効率的な方法は何ですか?
ボリューム上のすべてのファイルをスキャンしてグラフを描画するアプリケーションを作成しています。不便なことにScannerと呼ばれるフリーウェア プログラムに似ていますが、これはハード リンクを考慮しており、ハード リンクをチェックしなくても Java で達成できるよりも高速にスキャンします。
次の(遅い)方法でハードリンク数を確認しようとしました:
(例は読みやすくするために非常に単純化されています)
CMD プログラム経由STAT
(Windows)
process = Runtime.getRuntime().exec(new String[]{"stat", "--printf=%h", "\"" + filePath + "\""});
in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String inpMsg = in.readLine();
linkCount = Integer.parseInt(inpMsg);
への JNI 呼び出しを使用しますGetFileInformationByHandle
。
String lpFileName = filePath;
int dwShareMode = Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE;
Pointer lpSecurityAttributes = null;
int dwCreationDisposition = Kernel32.OPEN_EXISTING;
int dwFlagsAndAttributes = 0;
int hTemplateFile = 0;
hFile = Kernel32.INSTANCE.CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
Memory lpFileInformation = new Memory(56);
Kernel32.INSTANCE.GetFileInformationByHandle(hFile, lpFileInformation);
linkCount = lpFileInformation.getInt(40);
より高速な方法が必要な理由を理解するために、C: ドライブ (170000 ファイル) 上のすべてのファイルに対して、さまざまなプロセスがどれだけ高速に反復処理できるかを示します。
- C:\ で Alt+Enter: 1 秒あたり 19000 ファイル (9 秒)
- スキャナー (前述): 1 秒あたり 7800 ファイル (22 秒)
- Java (ハードリンクなし): 1750 ファイル/秒 (98 秒)
- Java (JNI を使用): 1 秒あたり 40 ファイル (1:10 時間 (予測))
- Java (STAT あり): 1 秒あたり 8 ファイル (5:50 時間 (予測))
File.listFiles()
Java が Scanner よりも遅いという事実は、新しい の代わりに使用しているという事実に関係している可能性がありますが、FileVisitor
ハード リンクがない場合よりも 43 倍遅い 40 ファイル/秒の速度は受け入れません。
(これらのテストは、以前に数回スキャンした後に実行しました。最初のスキャンには常に数倍の時間がかかります)