2011-12-16 14 views
0

ファイル本体の特定のパターンを見つけるために、ディスク内のファイルツリーを走査する単純なJavaアプリケーションを検討してください。ファイル内のテキストパターンを見つけるためのマルチスレッド化手法

マルチスレッドを使用すると、固定フォルダThreadPoolで新しいRunnableを送信する新しいフォルダが見つかった場合など、パフォーマンスを向上させることができます。実行可能なタスクは、新しいフォルダなどを見つけるためにフォルダを横断する必要があります。私の考えでは、この操作はIOバウンドでなければなりません。

ハードドライブの種類によって異なりますか? (hdd、... etc) OSの種類によって異なりますか?

IMHO唯一のことは、ファイル本体のパターンを見つけるためにファイル内容を解析するための新しいスレッドを生成することです。

この問題を解決する一般的なパターンは何ですか?それはマルチスレッドかシングルスレッドか?

+1

それは間違いなく、ディスクの種類によって異なります...シーク時間がない小さな問題です(あなたはSSDを使用しない場合には、ある)ので、ここでマルチスレッドを使用する利点はありません。 2つのファイルについて、それらを並行して読むと、OSはファイル1から読み込み、次にファイル2を探し、次にファイル2から読み込む必要があります。 – fge

+0

なぜそれを試してみませんか?ファイルバッファでパターンを検索すると、かなりCPUを消費します。従来のハードディスクのシーク時間は、ディスクがネットワークを介して接続されている場合でも、それほど大きな問題ではありません。 1つのバッファのシーク時間が、別のバッファのパターンをスキャンするのと並行して実行された場合、合理的な拡張と思われる。それを行って、何が起こるかを見てください!それがより良い、同じか悪いかどうか私たちに知らせてください。 –

答えて

2

テストプロジェクトで作業中にこの分野でいくつかの調査を行ったところ、githubのプロジェクトをhttp://github.com/4ndrew/filesearcherで見ることができます。もちろん、主な問題はディスクI/O速度ですが、読取り/並行して検索を実行するのに最適なスレッド数を使用すると、より良い結果を得ることができます。

UPD:はまた、この記事でhttp://drdobbs.com/parallel/220300055

1

タスクがCPUまたはIOバインドであるかどうかを判断し、マルチスレッド化の恩恵を受けるかどうかを判断する必要があることは間違いありませんでした。一般的に、ディスク操作は非常に遅いため、複雑なデータを解析して解析する必要がなければ、マルチスレッドのメリットがあまり得られません。私はちょうど簡単なテストを書いてみましょう。単一のスレッドで解析してファイルを読み込み、それを測定して解析を追加して、それがはるかに遅いかどうかを見て決定します。

ファイルを読み取り、データを(制限付き)キューに配置し、次に別のスレッド(またはExecutorServiceを使用する方がよい)がデータを解析する、2つのスレッドを使用するとよいでしょう。あなたは常に解析するスレッドの数を微調整することができます。複数の物理ディスクなどから読み込む必要がない限り、複数のスレッドでディスクを読み取るのが大変意味があるかどうかはわかりません。

1

あなたができることは次のとおりです。シングルプロデューサのマルチコンシューマパターンを実装します.1つのスレッドがディスクを検索し、ファイルを取得し、コンシューマスレッドが処理します。

この場合、複数のスレッドを使用してディスクをスキャンすると効果的ではありませんが、パフォーマンスが低下する可能性があります。ディスクが毎回次の読み取り位置を探す必要があるためです。ディスク間のディスク。

2

を見て、私はいくつかの時間前にちょうどこの質問にいくつかの実験をしました。最終的には、私がファイルにアクセスする方法を変えることで、はるかに良い改善を達成できると結論づけました。ここで

は私が最終的に使用してしまったファイルウォーカー:

// 4k buffer size ... near-optimal for Windows. 
static final int SIZE = 4 * 1024; 

// Fastest because a FileInputStream has an associated channel. 
private static void ScanDataFile(Hunter h, FileInputStream f) throws FileNotFoundException, IOException { 
    // Use a mapped and buffered stream for best speed. 
    // See: http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly 
    FileChannel ch = f.getChannel(); 
    // How much I've read. 
    long red = 0L; 
    do { 
    // How much to read this time around. 
    long read = Math.min(Integer.MAX_VALUE, ch.size() - red); 
    // Map a byte buffer to the file. 
    MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, red, read); 
    // How much to get. 
    int nGet; 
    // Walk the buffer to the end or until the hunter has finished. 
    while (mb.hasRemaining() && h.ok()) { 
     // Get a max of 4k. 
     nGet = Math.min(mb.remaining(), SIZE); 
     // Get that much. 
     mb.get(buffer, 0, nGet); 
     // Offer each byte to the hunter. 
     for (int i = 0; i < nGet && h.ok(); i++) { 
     h.check(buffer[i]); 
     } 
    } 
    // Keep track of how far we've got. 
    red += read; 
    // Stop at the end of the file. 
    } while (red < ch.size() && h.ok()); 
    // Finish off. 
    h.close(); 
    ch.close(); 
    f.close(); 
} 
関連する問題