En büyük tam sayı dizisini bellekte tutmak için gereken alan
Bir algoritmayı gözden geçiriyorum ve bir dizi tamsayı tutuyor, girdi boyutu dinamik. Hesaplamalarıma göre, şu kadar sürebilir:
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
Bu hesaplama doğru mu? JVM, int dizisini depolamak için bu kadar bitişik alanı kullanır mıydı yoksa dikkate alınması gereken başka şeyler var mı?
Yanıtlar
Dizinin teorik boyutu şöyle olacaktır:
numberOfElementsInTheArray * 4 bayt
12 bayt başlık (
int[]
bir Nesnedir). Aslında başlıkların boyutu, kullandığınız bayraklara ve bunu çalıştırdığınız JVM sürümüne bağlıdır.length
Diziyi korumak için 4 baytdolgu malzemesi.
Örneğin: (Bunun için JOL kullanacağım ):
int [] x = new int[10];
for(int i=0;i<10;++i){
x[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)x).toPrintable());
çıktı:
[I@7a81197dd object externals:
ADDRESS SIZE TYPE PATH VALUE
70fe45268 56 [I [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]
Yani var 56 bytes
:
- Değerlerin kendileri için 40 (10 inç * 4 bayt)
- Başlıklar için 12
- Uzunluk için 4
- Dolgu için 0
Bu diziyi olarak Integer
değiştirirseniz, işler çarpıcı biçimde değişir. Integer
bir Nesnedir, bu nedenle dizi içinde bir referans ( bayt olabilir 4
veya 8
bayt olabilir UseCompressedOops
), ayrıca her Integer
örnek 2 başlık gerektirir (her Integer
biri bir Nesnedir).
Integer[] y = new Integer[10];
for(int i=0;i<10;++i){
y[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());
hangisini gösterecek:
[Ljava.lang.Integer;@369f73a2d footprint:
COUNT AVG SUM DESCRIPTION
1 56 56 [Ljava.lang.Integer;
10 16 160 java.lang.Integer
11 216 (total)
Toplam 216 bytes
:
- Her referans için 4 bayt (açtım
UseCompressedOop
), toplam 40 bayt - Dizinin 12 bayt başlıkları
- Dizinin 4 bayt uzunluğu
- 0 bayt dolgu
Bu diziden gelen her referans, bir nesneye işaret eder Integer
, bu Nesnelerin her biri aşağıdakilere sahip olacaktır 16 bytes
:
- İç 4 bayt
int
tuttukları - 12 bayt başlık
- 0 bayt dolgu
Dizi boyutu maksimum < Integer.MAX_VALUE
Hayır, maksimum değeriniz yanlış.
Java'da bir dizideki öğe sayısı sınırı, Java Integer.MAX_VALUEsürümüne, ana işletim sistemine ve Java'nın nasıl derlendiğine bağlı olarak (2,147,483,647) ' den biraz daha azdır . Bkz bu Yanıtı Soru, Ivan Mamontov tarafından ben büyük boyutu ile bir dizi oluşturamıyor Neden? .
Evet, en büyük int
≈ 8 konser dizisi
Dolayısıyla, maksimum dizinin boyutu, int
kabaca ( Integer.MAX_VALUE - 8L ) * 32L
68,719,476,448 bit olan 8,589,934,556 sekizli bit olacaktır.
Yani evet, yaklaşık 8 konser hafıza. Ve unutmayın: bu bir dizi için bitişik hafızadır. Yani:
- Çalışma zamanında o anda belleğin ne kadar parçalanmış olduğuna bağlı olarak , JVM ve ana işletim sisteminin böyle bir diziyi üretmek için önemli çalışmaları olabilir .
- Ana bilgisayar donanımında yeterli gerçek bellek yoksa, ortaya çıkan sayfalamanın korkunç performansa yol açabileceği sanal belleğe geçeceksiniz.
İşinizde bu sınırları gerçekten zorluyorsanız her zaman gerçek dünya testleri yapın. Ayrıca, Zing by Azul Systems gibi çok büyük bellek için tasarlanmış alternatif Java uygulamalarını düşünmek isteyebilirsiniz .