2009-03-25 7 views
14

頻繁に使用されるオブジェクトのプールを維持し、新しいものを作成するのではなくプールからオブジェクトを取得するプロとは何ですか?文字列インターンングのようなものですが、すべてのクラスオブジェクトで可能です。オブジェクトプール

例えば、gc時間とオブジェクトの作成時間を節約するので、それは良いと考えることができます。一方、複数のスレッドから使​​用される場合、同期のボトルネックになる可能性があります。明示的な割り当て解除が必要で、メモリリークの可能性があります。再利用可能なメモリを確保することで、ガベージコレクタにさらなる負担がかかります。

+0

コメントは否定的ですが、似たようなものを考えていた。何千もの潜在的な境界ボックスオブジェクトを作成するj2meアプリケーションがあります。私はそれらのプールを作成することができれば、後でGCにもっと簡単な仕事を与えています。私はこれが依然として拘束された携帯電話の世界では悪い考えであるのだろうかと思います。 – izb

+0

高価なオブジェクトのみをプールします(データベース接続など)。 「高価」の定義は、要件に強く依存します。 –

答えて

18

オブジェクトが高価でない限り、私は気にしません。

利点:作成

  • 少ないオブジェクト - オブジェクトの作成が高価である場合、これは重要になります。 =

    • より複雑なコード
    • 共有リソース:

    マイナス面(標準的な例はおそらく、「作成」は、サーバへのネットワーク接続を行う等の認証を提供することを含むデータベース接続、です)ロック;潜在的なボトルネック

  • は、オブジェクトの寿命のGCの期待に違反(ほとんどのオブジェクトは短命されます)

はあなたが解決しようとしている実際の問題を持っていますか、またはこれは投機的ですか?あなたがベンチマーク/プロフィールのランを持っていて、そこに問題があることを示していない限り、私はこのようなことをすることについて考えません。

+0

私は、レイテンシに敏感なリアルタイムアプリケーションの中で世界がガーベジコレクターと呼ばれることによって、どんな詰まりも軽減することに実際興味があります。 – baskin

+0

さて、あなたはリアルタイムJavaを見ることができます。私はそれを自分で使ったことはありませんが、チェックする価値があります。 GCをチューニングしてみてください。そこにはたくさんのオプションがあります。もちろん、あなたのコードが待ち時間に敏感なビットの中に*どんな*オブジェクトも割り当てないようにすることができれば、それは素晴らしいことですが、難しいです。 –

+0

はい、私はJava RTSを見てきましたが、それが無料ではないために主に使用する傾向がありません。 GCチューニングも私が試していることです、特にCMS gcで遊んでいます。そのちょうど私は正しい最適なパラメータの組み合わせを打つことはないでしょう。 ご協力ありがとうございます。 – baskin

2

私はJon Skeetの意見に同意します。オブジェクトのプールを作成する特定の理由がない場合は、気にしません。

プールが本当に役に立つ/必要がある状況がいくつかあります。作成に費用がかかりますが、再利用できるリソース(データベース接続など)がある場合は、プールを使用することが理にかなっています。また、データベース接続の場合、プールは、アプリケーションがデータベースへの同時接続をあまりにも多く開くのを防ぐのに便利です。

21

最初の最適化の法則:しないでください。第二法則:あなたが実際にあなたが最適化する必要があるという事実を測定し、知っていなければ、それをしないでください。

実際にオブジェクトを作成するのが本当に高価で、実際に再利用できる場合(公開操作だけで状態を再利用できるものにリセットできます)、効果的です。

Javaでのメモリ割り当ては、無料です(コストは10 cpu命令に近かったですが、これは何もありません)。したがって、オブジェクトの作成を減らすだけで、コンストラクタに費やす時間が節約されます。これは、変更なしで再利用できる(データベース接続、スレッド)、実際に重いオブジェクトを使用した場合の利得です。同じ接続(同じスレッド)を再利用します。

GC時間は短縮されません。実際、それは悪化する可能性があります。移動世代GC(Javaの場合、または最大1.5まで)では、GC実行のコストは解放されたメモリではなく、生きたオブジェクトの数によって決まります。Aliveオブジェクトはメモリ内の別のスペースに移動されます(これはメモリ割り当てが非常に速いため、空きメモリは各GCブロック内で連続しています).とマークされる前に2,3回古い世代のメモリ空間に移動されます。

GCとしてのプログラミング言語とサポートは、一般的な使用方法を考慮して設計されています。多くの場合、一般的な使用法から遠ざけると、効率の悪いコードを読みにくくなる可能性があります。

+0

私は実際にはレイテンシに敏感なリアルタイムアプリケーションの世界的なガベージコレクタを言うことで妨害を減らすことに興味があります。あなたの言うことは意味がありますが、そのような決定を下すためにはベンチマークが必要であると私は同意します。 – baskin

+2

GC時間*を短縮することができます。プールを使用することで、レイテンシの低いアプリケーションで大きな成果を上げるなど、オブジェクトを割り当てる必要がなくなります。あなたには決して割り当てないことを確かめるのは本当の痛みです。 –

+0

(私はそれがGC時間を悪化させることも非常に簡単かもしれないことに同意します) –

5

しないでください。

これは2001年の考えです。今でも何か価値のある唯一のオブジェクト "プール"はシングルトンです。私はシングルトンを使用して、プロファイリングの目的でオブジェクトの作成を減らすだけです(コードに影響を与えるものをより明確に見ることができます)。

これ以外の目的は、メモリを断片的に分割しているだけです。

1,000,000個のオブジェクトの作成時にプロファイルを実行してください。それは重要ではない。

Old article here.

+1

ポストコンストラクタの初期化時間が重要でない場合、 –

9

プールは、あなたが、一般的に、オブジェクトは不変作ることができないことを意味します。これはデフケーシブコピーにつながり、最終的には新しい不変オブジェクトを作成した場合よりも多くのコピーを作ってしまいます。

不変性は必ずしも望ましいわけではありませんが、多くの場合、不変である可能性があります。それらを不変でないようにしてプールに再利用できるようにするのは、おそらく素晴らしい考えではありません。

確かにそれが問題であることがわかっていない限り、気にしないでください。コードを明確かつ容易に従わせるようにしてください。そして、それは十分に速いでしょう。そうでない場合は、コードが明快で、従うのが簡単であるという事実により、(一般的に)スピードアップが容易になります。

+1

+1私の痛みを知っている。私は、オブジェクトプールを削除することで重大なデータ破損のバグを解決しました。 Java 1.3と1.4でのプロファイリングは、プールが大きな勝利であることを示しました。1.5では、コードが遅くなりました。 – Darron

+0

プールに応じて異なります。 –

5

これは、オブジェクトを作成する頻度と比較して、がどれくらい高価になるかによって決まります。 ...たとえば、栄光の構造体であるオブジェクト(たとえば、アクセサー以外のメソッド)は、プールの実際のユースケースになります。

実際の例:多数の整数/階数のペアを生成するプロセスからn個の最高ランクの項目(整数)を繰り返し抽出する必要がありました。私は境界のある優先度のキューで "ペア"オブジェクト(整数と浮動小数点のランク値)を使用しました。ペアを再利用すること、キューを空にする、ペアを投げ捨て、再作成することで、主にJVMの全ライフを通して再配分する必要がないため、主にGC課金で20%のパフォーマンス向上をもたらしました。

3

オブジェクトプールは、通常、データベース接続のような高価なオブジェクトの場合にのみ有効です。 Java 1.4.2まで、オブジェクトプールはパフォーマンスを向上させることができましたが、Java 5.0オブジェクトプールの場合、ヘルプよりもパフォーマンスを損なう可能性が高く、多くの場合、オブジェクトプールが削除されてパフォーマンスが向上しました(簡略化)

関連する問題