Javaアプリケーションメモリを効率的にするにはどうすればよいですか?
-
16-09-2019 - |
質問
長寿命のオブジェクトがたくさんあるアプリケーションのヒープサイズの使用をどのように最適化しますか? (大きなキャッシュ、dbからたくさんのレコードを読み込む)
- 適切なデータ型を使用します
- Java.lang.Stringを避けて、他のデータ型を表す
- 重複したオブジェクトは避けてください
- 値が事前に既知の場合は、列挙を使用します
- オブジェクトプールを使用します
- string.intern()(良いアイデア?)
- 必要なオブジェクトのみをロード/保持します
一般的なプログラミングまたはJava特定の回答を探しています。ファンキーなコンパイラスイッチはありません。
編集:
ヒープ内で何百万回も現れることができるポジョのメモリ表現を最適化します。
ユースケース
- メモリに巨大なCSVファイルをロードする(pojosに変換)
- Hibernateを使用して、データベースから数百万のレコードを取得する
回答の履歴書:
- フライウェイトパターンを使用します
- 書き込みにコピーします
- 10mのオブジェクトに3つのプロパティをロードする代わりに、サイズ10mの3つの配列(またはその他のデータ構造)がある方が効率的ですか? (データを操作するのは苦痛かもしれませんが、あなたが本当に記憶が不足している場合...)
解決
どのようなオブジェクトを保存しようとしているかは言わないので、詳細なアドバイスを提供するのは少し難しいです。ただし、いくつかの(排他的ではない)アプローチは、順不同で、次のとおりです。
- 使う フライウェイトパターン 可能な限り。
- ディスクへのキャッシュ。がある多数 Javaのキャッシュソリューション。
- string.internが良いアイデアであるかどうかについては、いくつかの議論があります。見るここ 質問のためにre。 string.intern()、およびその適合性に関する議論の量。
- を利用してください 柔らかい また 弱いオンデマンドで再作成/リロードできるデータを保存する参照。見るここ キャッシュテクニックでソフト参照を使用する方法について。
保存しているオブジェクトの内部と寿命について詳しく知ると、より詳細な答えが得られます。
他のヒント
メモリプロファイラーを使用し、メモリが消費されている場所を確認し、それを最適化することをお勧めします。定量的な情報がなければ、効果がないか、実際に事態を悪化させるものを変えることになります。
あなたのオブジェクトが小さい場合、特にデータの表現を変更することを見ることができます。たとえば、行ごとに1つのオブジェクトではなく、各列にオブジェクト配列を備えた一連の列としてデータの表を表すことができます。これにより、個々の行を表す必要がない場合、各オブジェクトのオーバーヘッドを大量に節約できます。たとえば、12列と10,000,000行のテーブルでは、1,000万個(1列あたり1列)ではなく12個のオブジェクト(列あたり1個)を使用できます。
オブジェクトモデルの適切な正規化を確認し、値を複製しないでください。
Ahem、そしてそれが何百万ものオブジェクトであるなら、私はちょうど64ビットVMとたくさんのRAMを選ぶと思います;)
通常の「プロファイラー」は、すべての「ライブ」オブジェクトの概要が必要であるため、あまり役に立ちません。ヒープダンプアナライザーが必要です。お勧めします Eclipseメモリアナライザー.
文字列から始めて、重複したオブジェクトを確認してください。 FlightWeight、CopyOnWrite、Lazy Initializationなどのパターンを適用できるかどうかを確認してください(Googleが友達になります)。
ここからリンクされているこのプレゼンテーションをご覧ください。一般的なJavaオブジェクトとプリミティブのメモリ使用をレイアウトし、すべての余分なメモリがどこに行くのかを理解するのに役立ちます。
より少ないオブジェクトをメモリに保存するだけです。 :)ディスクにこぼれるキャッシュを使用するか、テラコッタを使用してヒープ(仮想)をクラスター化して、未使用の部品をメモリから洗い流し、透過的に障害します。
Peter Alredyが作成したポイントに何かを追加したい(彼の答えについてコメントすることはできません:()メモリプロファイラーを使用する方が常に良い(チェック Javaメモリプロファイラー)Inttution.80%の時間を無視しているルーチンは、それにいくつかの問題があります。
何百万もの整数やフロートなどがある場合は、アルゴリズムがプリミティブの配列でデータを表現できるかどうかを確認してください。これは、各ガベージコレクションの参照が少なく、CPUコストが低いことを意味します。
派手なもの:ほとんどのデータをRAMで圧縮してください。現在の作業セットのみを展開します。あなたのデータがうまく機能する可能性のある良い地域を持っている場合。
より良いデータ構造を使用します。 Javaの標準コレクションは、かなり記憶集中です。
より良いデータ構造とは何ですか
- コレクションのソースを見ると、コレクションへのアクセス方法に自分自身を制限すると、要素ごとのスペースを節約できることがわかります。
- コレクションの成長方法は、大規模なコレクションには良くありません。コピーが多すぎます。大規模なコレクションには、Btreeなどのブロックベースのアルゴリズムが必要です。
しばらく時間を費やして調整してください VMコマンドラインオプション, 、特にガベージコレクションに関するもの。これはオブジェクトで使用されるメモリを変更することはありませんが、多くのRAMを使用したマシン上のメモリ集約型アプリでのパフォーマンスに大きな影響を与える可能性があります。
Assign null
すべての価値variables
どちらですno longer
使用済み。したがってmake it available for Garbage collection
.De-reference the collections
使用が終了すると、GCはそれらを掃引しません。