10 個の整数と 10 個の整数配列を作成すると、占有される合計スペースに違いはありますか?
何百万ものレコードのブール配列を作成する必要があるため、配列自体がどれだけのスペースを占めるかを理解したいと考えています。
整数の配列は、整数とオブジェクト ヘッダーを保持するためのメモリ ブロックとして表されます。通常、オブジェクト ヘッダーは 32 ビット JVM の 32 ビット ワードを 3 つ使用しますが、これはプラットフォームに依存します。(ヘッダーには、いくつかのフラグ ビット、クラス記述子への参照、プリミティブ ロック情報用のスペース、および実際の配列の長さが含まれます。さらにパディング。)
したがって、10 個の int の配列は、おそらく13 * 4
バイトの領域を取ります。
の場合Integer[]
、各 Integer オブジェクトには 2 語のヘッダーと、実際の値を含む 1 語のフィールドがあります。また、参照用にパディングと 1 ワード (または 64 ビット JVM では 1 から 2 ワード) を追加する必要があります。これは通常、配列の要素ごとに 5 ワードまたは 20 バイトです... 一部の Integer オブジェクトが配列内の複数の場所に表示されない限り。
ノート:
いくつかの大まかな下限の計算:
各 int は 4 バイトを使用します。= 10 の 40 バイト
int 配列は、各コンポーネントに 4 バイト、さらに長さを格納するために 4 バイト、さらにそれへの参照を格納するためにさらに 4 バイトを使用します。= 48 バイト (+ すべてのオブジェクトを 8 バイト境界に揃えるためのパディング)
Integer は、少なくとも 8 バイトと、それへの参照を格納するためにさらに 4 バイトを使用します。= 10 に対して少なくとも 120
整数配列は、10 個の整数に少なくとも 120 バイトと長さの 4 バイトを使用し、配置のためのパディングが必要になる場合があります。さらに、それへの参照を格納するための 4 バイト。(@Marko は、スロットあたり約 28 バイトを測定したと報告しているため、10 個の配列の場合は 280 バイトになります)。
Javaには、Integerとintの両方があります。intを参照しているとすると、intの配列はオブジェクトと見なされ、オブジェクトにはメタデータがあるため、10個のintの配列は10個を超えるint変数を占有します。
あなたのコメントに照らして、配列を使用しても大きな違いはありません。配列は、その機能自体にごくわずかな量のメモリを使用します。他のすべてのメモリは、格納されたオブジェクトによって使用されます。
編集: 理解する必要があるのは、ブール ラッパーとブール プリミティブ型の違いです。通常、ラッパー タイプは、プリミティブよりも多くのスペースを占有します。したがって、レコードのミッションでは、プリミティブを使用してください。
あなたが言ったように、ミッションオブレコードを扱うときに留意すべきもう1つのことは、Javaオートボクシングです。配列全体をトラバースする関数でこれを意図せずに使用すると、パフォーマンスが大幅に低下する可能性があります。
教師や面接官に悪い影響を与える必要はありません。
メモリ内の変数のサイズとアラインメントをどの程度気にするかは、コードに必要なパフォーマンスの程度によって異なります。たとえば、ソフトウェアがトランザクション (EFT / 株式市場) を処理するかどうかは非常に重要です。
メモリ内の変数のサイズ、アラインメント、およびパッキングは、CPU キャッシュのヒット/ミスに影響を与える可能性があり、コードのパフォーマンスに最大 100 倍影響する可能性があります。
パフォーマンスを向上させるトリックを責任を持って使用する限り、低レベルで何が起こっているかを知ることは悪いことではありません。
たとえば、私はこの質問に対する正確な答えを知る必要があったため、このスレッドに来ました。これにより、プリミティブの配列のサイズを変更して、CPU キャッシュ ラインの整数倍を埋めることができます。これらの配列に対して計算を実行するコードが必要だからです。結果の消費者のために計算を準備する必要がある有限のウィンドウがあるため、プリミティブをすばやく実行する必要があります。
あなたができることは測定です:
public static void main(String[] args) {
final long startMem = measure();
final boolean[] bs = new boolean[1000000];
System.out.println(measure() - startMem);
bs.hashCode();
}
private static long measure() {
final Runtime rt = Runtime.getRuntime();
rt.gc();
try { Thread.sleep(20); } catch (InterruptedException e) {}
rt.gc();
return rt.totalMemory() - rt.freeMemory();
}
もちろん、これは標準的な免責事項にも当てはまります。gc()
特定の保証はありません。そのため、一貫した結果が得られるかどうかを確認するために数回繰り返します。私のマシンでは、答えは ごとに 1 バイトboolean
です。
RAMスペースに関しては、実際の違いはありません
配列を使用する場合、11 個のオブジェクト、10 個の整数、および配列があり、さらに配列には他のメタデータが含まれています。したがって、配列を使用すると、より多くのメモリ領域が必要になります。
今、本当です。この種の質問は、実際に就職の面接や試験で出てきます。それは、あなたがどんな種類の面接官や教師を持っているかを示しています... VM と OS 自体で非常に多くの抽象化のレイヤーが機能しているため、ポイントは何ですか?このことを考えて?マイクロ最適化メモリ...!
つまり、10個の整数と10個の整数配列を作成すると、占有される合計スペースに違いがあります。
(integer array of 10) = (10 integers) + 1 integer
最後の「+1整数」は配列のインデックス用です(配列は2,147,483,647個のデータを保持でき、これは整数です)。つまり、配列を宣言するときは、次のように言います。
int[] nums = new int[10];
実際には、メモリから 11 int スペースを予約します。配列要素の場合は 10、配列自体の場合は +1。