最大の整数配列をメモリに保持するために必要なスペース
アルゴリズムを確認していますが、整数の配列が保持されており、入力のサイズは動的です。だから私の計算によれば、それは同じくらいかかることがあります
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
この計算は正しいですか?JVMはこの非常に連続したスペースを使用してint配列を格納しますか、それとも他に考慮する必要があることはありますか?
回答
配列の理論上のサイズは次のようになります。
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バイトのパディング
最大配列サイズ< 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の代替実装を検討することもできます。