2

このコードを見てください:

MessageParser parser = new MessageParser();
for (int i = 0; i < 10000; i++) {
    parser.parse(plainMessage, user);
}

何らかの理由で、実行速度が(約100ms)遅くなります。

for (int i = 0; i < 10000; i++) {
    MessageParser parser = new MessageParser();
    parser.parse(plainMessage, user);
}

なぜ何かアイデアはありますか?テストは何度も繰り返されたので、それはただランダムではありませんでした。オブジェクトを1回作成するよりも、10000倍速く作成するにはどうすればよいでしょうか。

4

4 に答える 4

10

Javaには「世代別ガベージコレクション」があり、同じオブジェクト/メモリスペースを再利用していないことを(ループ内で)すばやく識別できるため、GCコストは実質的にゼロです。一方、あなたの長寿命のオブジェクトは、保育園の世代を超えた世代のパスを生き残り、メインの世代に移動する必要があります。

要約すると、パフォーマンスを適切に測定するためのテストを行わずに、パフォーマンスについて実際に想定することはできません。

于 2009-09-27T19:18:42.567 に答える
0

parserの範囲を制限しながら最初の例をベンチマークするとどうなりますか?

{
    MessageParser parser = new MessageParser();
    for (int i = 0; i < 10000; i++) {
        parser.parse(plainMessage, user);
    }
}
// `parser` no longer visible

オブジェクトを1つだけ作成する必要があるため、これが最速であると期待しparserます。VMは、ループの直後にgcを実行できることを認識しています。

于 2009-09-27T21:35:04.687 に答える
0

後続のパーサーの呼び出しで内部状態をクリーンアップするロジックが存在する場合があります。

GCはベンチマーク中に実行されましたか?新しいオブジェクトをインスタンス化するのはかなり安価であり、より速いケースで作成したすべてのオブジェクトを破棄する時間を数えないと、公平な比較にはなりません。

于 2009-09-27T19:18:02.247 に答える
0

何をしているのMessageParserか、どこから来ているのかわかりません。内部で「漏れ」ている可能性があります。もう1つの可能性は、オブジェクトが解析中に作成されたデータからさらに離れることです。これは、TLAミスが発生する可能性が高いことを意味します。また、MessageParserが内部状態を維持し、古い世代に移行した場合、新しいデータを参照していることに注意するGCの仕組みが問題になる可能性があります(「カードスコアリング」は頭に浮かぶ専門用語です)。

于 2009-09-27T19:22:26.460 に答える