9

gc スイープ時間を節約するために、gc の観点から収集不可能な Java オブジェクトをマークすることは可能ですか?

http://wwwasd.web.cern.ch/wwwasd/lhc++/Objectivity/V5.2/Java/guide/jgdStorage.fm.htmlの行に沿ったもの、特にそこにある非ガベージ収集可能コンテナ(非ガベージ-収集可能?)。

問題は、通常の一時オブジェクトがたくさんあることですが、キャッシュ用に保存されているオブジェクトがさらに大きい (数ギグ) ことです。Java GC は、収集するものを見つけようとしてこれらすべてのキャッシュ ギガバイトをトラバースする必要はありません。キャッシュ データには独自のタイムアウトがあるキャッシュ データが含まれているためです。

このようにして、カスタムの方法でデータを無限に存続するオブジェクトと通常に存続するオブジェクトに分割できます。通常のオブジェクトはそれほど長く存続せず、量が少ないため、GC が非常に高速になることを願っています。

この問題には、Apache DirectMemoryや Commercial Terracotta BigMemory(http://terracotta.org/products/bigmemory) などのいくつかの回避策がありますが、Java ネイティブのソリューションの方が優れています (つまり、無料で、おそらくより信頼性が高いということですか?)。また、シリアライゼーションのオーバーヘッドを避けたいと考えています。つまり、同じ jvm 内で発生する必要があります。私の理解では、DirectMemory と BigMemory は主にオフ ヒープで動作します。これは、オブジェクトを jvm の外部のメモリとの間でシリアル化/逆シリアル化する必要があることを意味します。jvm 内の非 gc 領域をマークするだけで、より良い解決策に思えます。キャッシュにファイルを使用することもオプションではありません。同じように、シリアライゼーション/デシリアライゼーションのオーバーヘッドが高くつきます。ユースケースは、大量のデータがランダム (人間の) 順序で使用され、低レイテンシーが必要な HA サーバーです。

4

5 に答える 5

2

JVM が管理するすべてのメモリも、JVM によってガベージ コレクションされます。また、直列化解除せずに Java メソッドで直接使用できる「ライブ」オブジェクトは、JVM メモリ内に存在する必要があります。したがって、私の理解では、ガベージ コレクションの影響を受けないライブ オブジェクトを持つことはできません。

一方、あなたが説明する使用法は、ガベージコレクションへの世代別アプローチを非常に効率的にするはずです。大きなオブジェクトがしばらく残っていると、再生のためにチェックされる頻度が低くなります。したがって、これらのチェックを回避することで得られるものはあまりないと思います。

于 2012-07-04T16:34:09.520 に答える
1

gc スイープ時間を節約するために、gc の観点から収集不可能な Java オブジェクトをマークすることは可能ですか?

いいえ、できません。

オブジェクトを到達可能な状態にしておくことで、オブジェクトがガベージ コレクションされるのを防ぐことができますが、GC はオブジェクトをトレースして、フルごとに到達可能性をチェックする必要があります。GC(少なくとも)。

jvmが飢えているとき、それらの不要なオブジェクトもすべてスキャンし始めるという私の仮定です。

はい。それは正しいです。ただし、この方法で処理したいオブジェクトが大量にない限り、オーバーヘッドは取るに足らないものになる可能性があります。(とにかく、より良いアイデアは、JVM により多くのメモリを与えることです...それが可能であれば。)

于 2012-07-04T16:52:44.433 に答える
0

推奨されるアプローチは、市販の RTSJ 実装を使用して GC を回避するか、オフ ヒープ メモリを使用することです。キャッシュのソフト参照も調べることができます (それらは収集されます)。

これはお勧めできません: 何らかの理由でこれらのオプションが十分でないと思われる場合は、UNSAFE (sun.misc.Unsafe の一部) であるダイレクト メモリ アクセスを調べることができます。「theUnsafe」フィールドを使用して、「Unsafe」インスタンスを取得できます。Unsafe では、'allocateMemory' および 'freeMemory' を介してメモリの割り当て/割り当て解除を行うことができます。これは GC の制御下になく、JVM ヒープ サイズによる制限もありません。このルートをたどると、GC/アプリケーションへの影響は保証されません。そのため、RTSJ のような実装を使用していない場合は、バイト バッファーを使用することをお勧めします。

お役に立てれば。

于 2012-07-04T17:23:28.217 に答える
0

簡単に言えば、これを行うには、ガベージ コレクション アルゴリズムがそのようなフラグを認識し、作業を行う際にそれを考慮する必要があります。

このようなフラグを持つ標準の GC アルゴリズムを知らないので、これを機能させるには、独自の GC アルゴリズムを作成する必要があります (この情報を通信するための実行可能な方法を決定した後)。

原則として、実際、あなたはすでにこの道を歩み始めています。JVM の GC アルゴに喜んで任せるのではなく、ガベージ コレクションをどのように行うべきかを決定しているのです。あなたが説明した状況は、あなたにとって測定可能な問題ですか。既存のガベージ コレクションでは不十分ですが、あなたの計画はうまくいきますか? ガベージ コレクターは非常によく調整されているため、「非効率的な」デフォルトの戦略が実際に単純に最適な戦略よりも高速であっても驚かないでしょう。

(手動でメモリ管理を行うのは、最善の場合でもトリッキーであり、エラーが発生しやすくなります。一部のメモリを自分で管理し、ストック ガベージ コレクタを使用して残りのメモリを処理するのは、さらに悪いことのように思えます。GC がヒープ全体で何が起こっているかを「知っている」と仮定していますが、これはもはや真実ではありません。できれば避けてください...)

于 2012-07-04T16:58:45.653 に答える
0

生きている Java オブジェクトは、常にGC ライフサイクルの一部です。または、別の言い方をすれば、オブジェクトを非 gc としてマークすることは、ルート参照 (たとえば、静的な最終マップ) によってオブジェクトを参照することと同じ順序のオーバーヘッドです。

しかし、もう少し考えてみると、キャッシュに入れられたデータは一時的なものである可能性が最も高く、最終的には削除されます。その時点で、JVM と GC が好きになり始めます。数百 GB の永続データがある場合は、アプリケーションのアーキテクチャを再考し、データを分割して分散することをお勧めします (水平方向のスケーラビリティ)。

最後に大事なことを言い忘れましたが、シリアライゼーションに関して多くの作業が行われ、シリアライゼーションのオーバーヘッド (ObjectInputStream と ObjectOutputStream の評判が悪いことについて話しているわけではありません) はそれほど大きくありません。それ以上に、データが主にプリミティブ型 (bytes 配列を含む) で構成されている場合、オフヒープバッファーから readInt() または readBytes() を効率的に実行する方法があります (インスタンスnetty.io の ChannelBuffer の場合)。これは進むべき道かもしれません。

于 2012-07-04T19:30:19.243 に答える