1

申し訳ありませんが、コードを投稿できませんが、バッファー サイズとして 50000000 バイトが設定された bufferedreader があります。HDD ライトが 2 分ごとに点滅し、大量のデータを読み取り、CPU が処理するにつれて再び静かになります。しかし、約 30 分後 (これは非常に大きなファイルです)、一度に 1 バイトずつ読み取っているように、HDD がスラッシングを開始します。それはまだ同じループにあり、空きRAMをチェックしてスワッピングを除外したと思います(ヒープサイズはデフォルトです)。

役に立つ回答は得られないかもしれませんが、試してみる価値はあります。

OKヒープサイズを768mbに変更しましたが、まだ何もありません。十分な空きメモリがあり、java.exe は約 300 MB しか使用していません。

今、私はそれをプロファイリングしましたが、ヒープは約 200MB にとどまり、利用可能な量をはるかに下回っています。CPU は 50% のままです。それでも、HDD は狂ったようにスラッシングし始めます。何も思いつきません。すべてを C# で書き直すつもりです。それが私の解決策です。

コードは次のとおりです (これは使い捨てのスクリプトであり、きれいではありません)。

    BufferedReader s = null;
    HashMap<String, Integer> allWords = new HashMap<String, Integer>();
    HashSet<String> pageWords = new HashSet<String>();
    long[] pageCount = new long[78592];
    long pages = 0;

    Scanner wordFile = new Scanner(new BufferedReader(new FileReader("allWords.txt")));
    while (wordFile.hasNext()) {
        allWords.put(wordFile.next(), Integer.parseInt(wordFile.next()));
    }
    s = new BufferedReader(new FileReader("wikipedia/enwiki-latest-pages-articles.xml"), 50000000);
    StringBuilder words = new StringBuilder();
    String nextLine = null;
    while ((nextLine = s.readLine()) != null) {
        if (a.matcher(nextLine).matches()) {
            continue;
        }
        else if (b.matcher(nextLine).matches()) {
            continue;
        }
        else if (c.matcher(nextLine).matches()) {
            continue;
        }
        else if (d.matcher(nextLine).matches()) {
            nextLine = s.readLine();
            if (e.matcher(nextLine).matches()) {
                if (f.matcher(s.readLine()).matches()) {
                    pageWords.addAll(Arrays.asList(words.toString().toLowerCase().split("[^a-zA-Z]")));
                    words.setLength(0);
                    pages++;
                    for (String word : pageWords) {
                        if (allWords.containsKey(word)) {
                            pageCount[allWords.get(word)]++;
                        }
                        else if (!word.isEmpty() && allWords.containsKey(word.substring(0, word.length() - 1))) {
                            pageCount[allWords.get(word.substring(0, word.length() - 1))]++;
                        }
                    }
                    pageWords.clear();
                }
            }
        }
        else if (g.matcher(nextLine).matches()) {
            continue;
        }
        words.append(nextLine);
        words.append(" ");
    }
4

6 に答える 6

1

読んでいるファイルが非常に大きい場合、次の行を使用すると、ファイルの大部分がStringBuilderを介してメモリにコピーされる可能性があります。プロセスのメモリフットプリントが大きくなりすぎると、ガベージコレクターを交換したり、スピンさせたりする可能性があります。

...
words.append(nextLine);
words.append(" ");
于 2011-01-02T10:14:00.820 に答える
1

バッファ サイズを削除して、デフォルトで試してみましたか?

于 2011-01-02T02:33:00.817 に答える
1

ファイルのバッファリングが機能していない可能性がありますが、プログラムが十分なメモリを使い果たしており、仮想メモリ システムがディスクへのページ スワップを行っている可能性があります。バッファ サイズを小さくするとどうなりますか? もっと大きいのはどうですか?

于 2011-01-02T02:33:21.680 に答える
1

ヒープ スペースが不足していて、連続して GC を実行するのに行き詰まっているに違いありません。その間に何が起こっているかを確認するためにアプリをプロファイリングしましたか? また、 -verbose:gc を指定して実行して、ガベージ コレクションの発生を確認してください。のように大きなヒープから始めてみることもできます」

-Xms1000m -Xmx1000m

これにより 1 GB のヒープが得られるため、それをすべて使い切ると、現在よりもはるかに遅くなるはずです。

于 2011-01-02T02:36:04.500 に答える
0

Java と IO の読み取りに何か問題があると考える前に、できるだけ速くファイルを読み取る単純なプログラムを作成することをお勧めします。デフォルトのバッファリングでは、ファイル サイズに関係なく、20 MB/秒以上でファイルを読み取ることができるはずです。アプリケーションを削除してファイルを読み取るだけにすることで、これを実行できるはずです。次に、ファイルの読み取りにかかる時間を自分で証明できます。

かなり多くの高価な操作を使用しました。おそらく、プロファイラーを使用してパーサーをより効率的にする方法を検討する必要があります。例えば

word.substring(0, word.length() - 1) 

と同じです

word

したがって、最初の if 句と 2 番目の if 句は同じです。

于 2011-01-02T10:29:11.270 に答える
0

うまくいけば、これが役立つかもしれません: http://www.velocityreviews.com/forums/t131734-bufferedreader-and-buffer-size.html

于 2011-01-02T02:28:57.663 に答える