5

(Java のメモリ マップ ファイル)を試すためMappedByteBufferに、単純なwc -l(テキスト ファイルの行数) デモを作成しました。

int wordCount(String fileName) throws IOException {
    FileChannel fc = new RandomAccessFile(new File(fileName), "r").getChannel();
    MappedByteBuffer mem = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());

    int nlines = 0;
    byte newline = '\n';

    for(long i = 0; i < fc.size(); i++) {
        if(mem.get() == newline)
            nlines += 1;
    }

    return nlines;
}

約 15 MB (15008641 バイト)、100k 行のファイルでこれを試しました。私のラップトップでは、約13.8 sec. なぜそんなに遅いのですか?

完全なクラス コードはこちら: http://pastebin.com/t8PLRGMa

参考までに、Cで同じ考えを書きました: http://pastebin.com/hXnDvZm6

約 28 ミリ秒で実行され490 times fasterます。

好奇心から、Java と本質的に同じアルゴリズムと API を使用する Scala バージョンも作成しました。実行されます。これは10 times faster、何か奇妙なことが起こっていることを示しています。

更新: ファイルは OS によってキャッシュされるため、ディスクの読み込み時間はかかりません。

RAMに収まらない可能性のある大きなファイルへのランダムアクセスにメモリマッピングを使用したかったのです。そのため、BufferedReader を使用しているだけではありません。

4

1 に答える 1

10

fc.size()がループ内で呼び出されるため、コードは非常に低速です。

fc.size()ファイルサイズは実行時に変更される可能性があるため、JVMは明らかに削除できません。基礎となるファイル システムへのシステム コールが必要なため、ファイル サイズのクエリは比較的低速です。

これをに変更

    long size = fc.size();
    for (long i = 0; i < size; i++) {
        ...
    }
于 2016-04-02T13:28:32.540 に答える