2009-08-09 8 views
44

Java WeakReferenceオブジェクトの作成とガベージコレクションに必要な実行時コストについて、誰かが調査しましたか?マルチスレッドアプリケーションのパフォーマンスに関する問題(競合など)はありますか?Javaの弱参照を使用するコスト

編集:明らかに実際の回答はJVMに依存しますが、一般的な観察も歓迎します。

EDIT 2:誰かがパフォーマンスのベンチマークを行ったか、ベンチマーク結果を指し示すことができれば理想的です。 (申し訳ありませんが、賞金は切れています...)

+0

明らかに、これはJDKの実装、SunとIBM vs JRockitなどによって異なります。 –

+4

[Goetz](http://www.ibm.com/developerworks/java/library/j- jtp01246/index.html):*各ガベージコレクションでは、ライブ参照オブジェクトのリストを構築しなければならず、各参照は適切に処理されなければなりません。その時。参照オブジェクト自体はガベージコレクションの対象となり、参照先の前に収集することができますが、その場合はエンキューされません。 – assylias

答えて

12

WeakReferencesはCMSのガベージコレクタに悪影響を及ぼします。私のサーバーの動作から見る限り、それは並列発言段階の時間に影響します。この段階では、すべてのアプリケーションスレッドが停止するため、非常に望ましくないことです。だからWeakReferencesに注意する必要があります。

+0

これは申し訳ありませんが、Sunフォーラムでこのような動作の理由を把握しようとしています:) – Vitaly

+2

ビタリー、これでもうこれはありますか? Sunのフォーラムでいくつかの情報を見つけたら、リンクを投稿できますか?ありがとう! – Owen

+0

彼らはどんな影響を与えているのですか?gcが弱い参照などを特別に必要とするので、明らかにコストがあります。 –

3

弱い参照を使用するキャッシュは、オンデマンドで再構築する場合などにアプリの速度を大幅に低下させる可能性があります。ゲッターに:

public Object getSomethingExpensiveToFind() { 
    if(cache.contains(EXPENSIVE_OBJ_KEY)) { 
     return cache.get(EXPENSIVE_OBJ_KEY); 
    } 

    Object sth = obtainSomethingExpensiveToFind(); // computationally expensive 
    cache.put(EXPENSIVE_OBJ_KEY, sth); 
    return sth; 
} 

このシナリオを想像:

1)アプリは、GCは、このようにキャッシュがあまりにも

3)アプリが続くクリアされ、弱い参照をクリーン)メモリ

2上で不足していますgetSomethingExpensiveToFind()などの多くのメソッドが呼び出され、キャッシュが再構築されます。

4)アプリのメモリが不足しています

その上

5)GCは、参照を着用クリーンキャッシュ

6をクリア)アプリは、getSomethingExpensiveToFind(のようなメソッドの多くを続けて)呼び出され、再び

7をキャッシュを再構築している)と...

私はこのような問題に遭遇しました。アプリケーションはGCによって頻繁に中断され、キャッシングの全ポイントを徹底的に打ち負かしました。

不適切な管理をすると、弱い参照がアプリ​​ケーションの処理速度を低下させる可能性があります。

+1

これは私が尋ねた質問には答えません。基本的には、オブジェクトキャッシュのスラッシングのため、弱い参照を賢明に使用するとパフォーマンスが悪くなる可能性があります。しかし、疑問は、弱い参照自体のオーバーヘッドについてです。 (理想的には、それらのオーバーヘッドの実際の測定値を与える答えが欲しいですが、私はそれらがどのように発生したかについての権威ある*説明についても解決します) –

+0

* metrics *と* benchmarks *具体的には – mantrid

+0

でした。ボーナス通知で。あなたはそれを読んだのですか?しかし、とにかく、あなたの答えは明らかに尋ねられた質問とは関係ありません。 –

4

私はJavaガベージコレクタを一度実装しました。これで実現できるものは、可能な限り弱いものです。

私の実装では、ガベージコレクション中に訪問されると、各弱参照の追加のオーバーヘッドがわずかに一定です。

結論は:私はそれについて心配するつもりはありません、あなたが弱い参照のzillionsを使用していない限り大きな問題ではありません。

最も重要なことに、コストは、ヒープ全体のサイズではなく、存在する弱い参照の数に比例します。

しかし、弱参照をサポートするガベージコレクタは、そうでないものと同じ速さであるとは言えません。ここで想定される疑問は、Javaが弱い参照をサポートしていることを考えると、それらを使用するための増分コストはいくらですか?

私は単純な「世界を止める」マーク/スイープガベージコレクタでした。ガベージコレクションの間、オブジェクトが生存しているかどうかをすべてのオブジェクトについて判定し、オブジェクトヘッダにLIVEビットを設定します。それから、それは通過し、すべての非ライブオブジェクトを解放します。

はあなただけで、次を追加し、弱い参照を処理するには、次の LIVEビット(すなわち、それらが参照されたオブジェクト上の LIVEビットがセットされることはありません)を設定するとき
  • は弱参照を無視します。
  • スイープステップ中に、次のような特別なチェックを追加します。訪問しているオブジェクトがLIVEであり、そのオブジェクトがWeakReferenceの場合は、弱く参照しているオブジェクトを確認し、そのオブジェクトがLIVEでない場合は、 。

このロジックの小さなバリエーションは、ソフトリファレンスとファントムリファレンスで機能します。

あなたが本当に興味があるなら、実装はhereです。

+0

これは非常に興味深いです。 (私はHotSpotの実装は異なっていると思います。)finalizeメソッドが参照されるオブジェクトを再リンクする場合は、どのように処理しますか?それは(部分)再マークをトリガーする必要はありませんか? –

+0

私はHotSpotの実装が異なるだけでなく、もっと洗練されたものであることを100%確信しています:) Re:ファイナライズしていないのは、ライブ以外のオブジェクトのための余計なステップです。実際には、「すべての非ライブオブジェクトをファイナライズするために通過してエンキューする」と言わなければなりません。 – Archie

+0

Re:ファイナライズでは、 'finalize()'が呼び出されたかどうかを示すビットをオブジェクトヘッダーに設定しなければなりません。したがって、実際には '-LIVE'以外のオブジェクトは、ビットがセットされていない場合はファイナライズのためにエンキューされ、ビットがセットされていればすぐに解放されます。 – Archie

関連する問題