膨大な量のテキストをスキャンして単語の頻度を数えたいと思います(実際にはNLP / IRに精通している人にとってはn-gramの頻度です)。これにはJavaHashMapを使用します。つまり、テキストを1行ずつ処理します。行ごとに単語を抽出し、単語ごとにハッシュマップの対応する頻度を更新します。
問題は、このプロセスがどんどん遅くなることです。たとえば、約10万行/秒の処理から始まり、パフォーマンスはすぐに低下し始めます。約2800万行を超えると、パフォーマンスは1秒あたり16k行に低下し、もちろん低下し続けます。
最初に頭に浮かんだのは、ハッシュマップのエントリが多すぎることが原因で、すべてのプットとすべての取得が毎回遅くなることでした。したがって、私が試したのは、常に最も頻繁な(たとえば100k)エントリのみをハッシュマップに保持することでした。これは、頻度を単語にマップする2番目のマップを使用して行われました(ここのように:Javaの値マップによって自動的にソートされます)
これは一般的にはるかに高速に実行されました。(56 kライン/秒で開始しましたが、28 milラインに達するまでに、パフォーマンスは36.5kライン/秒にしか低下していませんでした)。しかし、これもはるかに遅い速度で下降し続けました-しかし、それが下降し続けたという事実は残っています。
ハッシュマップのサイズが同じままであるのに、なぜこれが発生するのかについて、考えられる説明はありますか?これはガベージコレクターと関係があると思いますか?つまり、私がハッシュマップとの間でオブジェクトを出し入れし続けるという事実は、メモリか何かを断片化しますか?それとも、ハッシュ関数の問題でしょうか?私は文字列を使用しているので、ハッシュ関数はJavaの文字列のデフォルトのハッシュ関数です。
前述のタスクを実行するコードの一部は次のとおりです。
注:私はJavaの初心者なので、回答を詳しく説明することは大歓迎です。