最大の整数配列をメモリに保持するために必要なスペース

Jan 04 2021

アルゴリズムを確認していますが、整数の配列が保持されており、入力のサイズは動的です。だから私の計算によれば、それは同じくらいかかることがあります

  integer MAX_VALUE  * int size  = ?   
      2^31 integers  * 4 bytes   = ?
2147483648 integers  * 4 bytes   = 8 Gigabytes

この計算は正しいですか?JVMはこの非常に連続したスペースを使用してint配列を格納しますか、それとも他に考慮する必要があることはありますか?

回答

3 Eugene Jan 05 2021 at 01:39

配列の理論上のサイズは次のようになります。

  • numberOfElementsInTheArray * 4バイト

  • 12バイトのヘッダー(int[]オブジェクトです)。実際、ヘッダーのサイズは、使用したフラグと、これを実行しているJVMのバージョンによって異なります。

  • length配列を保持するための4バイト

  • パディング。

例:(これにはJOLを使用します):

    int [] x = new int[10];
    for(int i=0;i<10;++i){
        x[i] = 9999;
    }
    System.out.println(GraphLayout.parseInstance((Object)x).toPrintable()); 

出力します:

 [I@7a81197dd object externals:
      ADDRESS       SIZE TYPE PATH                           VALUE
    70fe45268         56 [I                                  [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]

だからそれは持っています56 bytes

  • 値自体は40(10 int * 4バイト)
  • ヘッダーの場合は12
  • 長さは4
  • パディングの場合は0

この配列をIntegerに変更すると、状況は劇的に変化します。Integerはオブジェクトであるため、配列内に参照を格納します(フラグに応じて、4または8バイトになる可能性がありますUseCompressedOops)。さらに、各Integerインスタンスには2つのヘッダーが必要です(それぞれIntegerがオブジェクトです)。

    Integer[] y = new Integer[10];
    for(int i=0;i<10;++i){
        y[i] = 9999;
    }

    System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());

表示されます:

   [Ljava.lang.Integer;@369f73a2d footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1        56        56   [Ljava.lang.Integer;
    10        16       160   java.lang.Integer
    11                 216   (total)

合計216 bytes

  • 参照ごとに4バイト(UseCompressedOopオンにしました)、合計40バイト
  • 配列の12バイトのヘッダー
  • 配列の4バイト長
  • 0バイトのパディング

その配列からの各参照はを指しInteger、それらの各オブジェクトは次のようになります16 bytes

  • intそれらが保持する内部の4バイト
  • 12バイトのヘッダー
  • 0バイトのパディング
1 BasilBourque Jan 04 2021 at 15:23

最大配列サイズ< Integer.MAX_VALUE

いいえ、最大値は正しくありません。

Javaの配列内の要素数の制限は、JavaInteger.MAX_VALUEのバージョン、ホストOS、およびJavaのコンパイル方法に応じて、(2,147,483,647)より少し少なくなります。質問については、Ivan Mamontovによるこの回答を参照してください。大きなサイズの配列を作成できないのはなぜですか?。

はい、int約8ギグの最大の配列

したがって、の最大配列のサイズは、intおよそ( Integer.MAX_VALUE - 8L ) * 32Lビットであり、68,719,476,448ビットであり、8,589,934,556オクテットです。

そうです、約8ギガのメモリです。そして覚えておいてください:これは配列の連続したメモリです。そう:

  • 実行時のその時点でのメモリの断片化の程度によっては、JVMとホストOSの側で、このような配列を生成するための重要な作業が行われる場合があります。
  • ホストハードウェアに十分な実メモリがない場合は、仮想メモリにラップインし、結果としてページングがひどいパフォーマンスにつながる可能性があります。

仕事でこれらの限界を本当に押し上げているのであれば、常に実際のテストを行ってください。また、Zing by Azul Systemsなど、非常に大きなメモリ用に設計されたJavaの代替実装を検討することもできます。