En büyük tam sayı dizisini bellekte tutmak için gereken alan

Jan 04 2021

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

3 Eugene Jan 05 2021 at 01:39

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.

  • lengthDiziyi korumak için 4 bayt

  • dolgu 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 Integerdeğiştirirseniz, işler çarpıcı biçimde değişir. Integerbir Nesnedir, bu nedenle dizi içinde bir referans ( bayt olabilir 4veya 8bayt olabilir UseCompressedOops), ayrıca her Integerörnek 2 başlık gerektirir (her Integerbiri 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 inttuttukları
  • 12 bayt başlık
  • 0 bayt dolgu
1 BasilBourque Jan 04 2021 at 15:23

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, intkabaca ( Integer.MAX_VALUE - 8L ) * 32L68,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 .