大規模なデータ構造を使用する場合、Java(Eclipse) での「メモリ不足エラー」を回避しますか?

StackOverflow https://stackoverflow.com/questions/2459972

質問

残念ながら、作業を完了するために巨大なデータ構造を使用する必要があるプログラムを作成していますが、初期化中に「メモリ不足エラー」が発生して失敗します。それが何を意味するのか、なぜそれが問題なのかはよく理解していますが、プログラムではこの大きな構造を使用する必要があり、それを保存する他の方法がわからないため、それを克服するのに苦労しています。

プログラムはまず、私が提供した大量のテキスト ファイルのコーパスにインデックスを付けます。これはうまくいきます。

次に、このインデックスを使用して大きな 2D 配列を初期化します。この配列には n² 個のエントリが含まれます。「n」はテキストのコーパス内の一意の単語の数です。私がテストしている比較的小さなチャンク (約 60 ファイル) では、約 30,000x30,000 のエントリを作成する必要があります。意図した完全なコーパスでも実行すると、これはおそらくさらに大きくなるでしょう。

インデックス作成後、データ構造の初期化中 (後で作業します)、毎回一貫して失敗します。

私が行ったことには次のようなものがあります。

  • プリミティブを使用するようにコードを修正する int[] の代わりに TreeMap
  • 冗長な構造を排除するなど...
  • また、プログラムを実行しました-Xmx2g 割り当てられたメモリを最大限に活用するには

これは単純なコード行の解決策ではなく、非常に新しいアプローチが必要になる可能性が高いと私は確信しています。そのアプローチが何なのかを探しているのですが、何かアイデアはありますか?

ありがとう、B。

役に立ちましたか?

解決

(配列の使用目的についていくつかの仮定を置くと) ほとんどのエントリは 0 になるようです。その場合は、 スパース行列 表現。

もし本当に 持っている それだけの数のエントリ (現在の配列はどこかにあります) すでに3ギガバイトを超えています, たとえオーバーヘッドがないと仮定しても)、その場合は、ある種のディスク上のストレージ、または遅延ロード/アンロード システムを使用する必要があります。

他のヒント

メモリ不足の問題にはいくつかの原因があります。

まず、最も単純なケースは、単により多くのヒープが必要な場合です。プログラムが 2G で正しく動作する場合、最大 512M のヒープを使用していることになります。増加はあります -Xmx2048m JVM オプションとして選択すれば問題ありません。また、64 ビット VM は、データの構成に応じて 32 ビット VM の最大 2 倍のメモリを使用することにも注意してください。

問題がそれほど単純でない場合は、最適化を検討してください。オブジェクトをプリミティブなどに置き換えます。これはオプションかもしれません。あなたが投稿した内容からは何とも言えません。

しかし最終的には、次のいずれかを選択しなければならない岐路に直面します。 仮想化 そして パーティショニング.

仮想化 この文脈では、実際よりも多くのメモリがあるかのように振る舞うことを単に意味します。オペレーティング システムはこれを仮想アドレス空間で使用し、ハード ディスク領域を追加メモリとして使用します。これは、一度にデータ構造の一部のみをメモリに保持し、残りを二次ストレージ (ファイルやデータベースなど) に永続化することを意味します。

パーティショニング データを複数のサーバー (実サーバーまたは仮想サーバー) に分割します。たとえば、NASDAQ で株式取引を追跡している場合、サーバー 1 には「A」、サーバー 2 には「B」などで始まる銘柄コードを配置できます。相互通信はスケーラビリティを制限するものであるため、相互通信の必要性を減らすか排除するようにデータをスライスする合理的なアプローチを見つける必要があります。

非常に単純なケースで、保存しているものが 30,000 個の単語と 30,000 x 30,000 個の単語の組み合わせである場合、それを 4 つのサーバーに分割できます。

  • 午前×午前
  • A-M x N-Z
  • N-Z x A-M
  • N-Z x N-Z

それは単なる 1 つのアイデアです。繰り返しになりますが、詳細を知らずにコメントするのは困難です。

これは、大規模なデータセットを扱う共通の問題です。データセットはもう少しあなたはまだ吸っている成長するとすぐにあなたが好きなだけを最適化することができますが、メモリが十分に(おそらく)になることはありません、と。最もスケーラブルなソリューションは、チャンクに、メモリ内の作業を少なく維持し、ディスク上の構造(データベース/ファイル)を永続化するだけです。

あなたは、このようなトリックを行うだろうバイトとして、あなたの2次元配列で、おそらく小さいタイプの各値の完全な32ビット(整数のサイズ)を必要としない場合は?また、あなたは可能性としてそれをできるだけ多くのヒープスペースを与える必要があります - 2ギガバイトは、近代的なシステムのために、まだ比較的小さいです。 RAMを使用すると、インメモリ処理の多くをやっていると期待している場合は特に、安価である。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top