2

以下のように2D配列を作成しようとしています。

int NUM_RECORDS = 100480507;

byte[][] completeArray = new byte[NUM_RECORDS][6];

持っているだけで十分ではないでしょうか100480507 * 6 ~= 0.6 GB

この質問も参照してください。

しかし、この配列を作成するとメモリが不足します。JVM 引数を介して Java プロセスに 4G を割り当てました。

それはどのように説明できますか?ここで些細なことを見逃していますか?

これは私のプログラムです

public class MemTest {

   public static void main(String[] args) {
       int NUM_RECORDS = 100480507;
       byte[][] completeArray = new byte[NUM_RECORDS][6];
       System.out.println("Array created");
   }
}
4

2 に答える 2

2

各配列にはオーバーヘッドがあります (たとえば、オーバーヘッドに関する IBM ドキュメントを参照してください -> http://www.ibm.com/developerworks/java/library/j-codetoheap/index.html )。あなたの場合、100480507 個を作成しています。

コードを「byte[] completeArray = new byte[ NUM_RECORDS*6 ];」に変更すると、理論によれば、同じスペースが必要になるはずです! しかし、オーバーヘッドが最小限であるため、これが機能することはかなり確信しています。また、「byte[][] completeArray = new byte[6][NUM_RECORDS] ;」を試すこともできます。それもうまくいくはずです(オーバーヘッドが少ない)。

これで問題が解決しないことはわかっていますが、オーバーヘッドについての見通しが得られることを願っています。

于 2013-02-01T09:29:20.657 に答える
1

Harmony JVM のオブジェクト レイアウトを確認します (JVM の他の実装も同様だと思います)。Java の各オブジェクトには、JVM の重要な情報を含むオブジェクト ヘッダーがあります。最も重要なのは、オブジェクトのクラス ( 1 語) への参照です。さらに、GC によって使用され、同期を管理するために使用されるフラグがいくつかあります。つまり、ロックワード (すべてのオブジェクトを同期できるため) が別の1 ワードを占めます(部分的なワードを使用するとパフォーマンスが低下します)。これは 2 ワードで、32 ビット システムでは 8 バイト、64 ビット システムでは 16 バイトです。配列にはさらに、配列の長さの int フィールドが必要です。これはさらに4 バイト、場合によっては8 バイトです。64 ビット システムで。したがって、配列ごとに、32 ビット マシンでは 12 バイトが追加され、64 ビット マシンでは 24 バイトになる場合があります。

プログラムには、6 つの配列の配列があります。100480507 1D 配列。したがって、追加のメモリ消費量は約 1.2 + 0.6 GB であり、これは連続メモリの非常に大きなブロックです。オーバーヘッドは約 200% です。

コードを次のように変更すると:

public class MemTest {
   public static void main(String[] args) {
       int NUM_RECORDS = 100480507;
       byte[] completeArray = new byte[NUM_RECORDS * 6];
       System.out.println("Array created");
   }
}

作成する配列は 1 つだけなので、オーバーヘッドは非常に小さくなります。合計で約0.6GB。

コードが次のように変更されたとき:

public class MemTest {
   public static void main(String[] args) {
       int NUM_RECORDS = 100480507;
       byte[][] completeArray = new byte[NUM_RECORDS][6];
       System.out.println("Array created");
   }
}

全部で 7 つの配列を取得しました。プログラムはすぐに終了します。

コード スタイルで別の 0.6GB メモリを作成しますが、要素の型を int から long に変更します。

public class MemTest {
   public static void main(String[] args) {
       int NUM_RECORDS = 12560063;
       long[][] completeArray = new long[NUM_RECORDS][6];
       System.out.println("Array created");
   }
} 

プログラムはすぐに終了することもできます。オーバーヘッドは約 150M/600M = 25% です。

于 2013-02-01T08:03:17.223 に答える