Ruang yang dibutuhkan untuk menyimpan array bilangan bulat terbesar dalam memori

Jan 04 2021

Saya meninjau algoritma dan itu membuat array bilangan bulat, ukuran input dinamis. Jadi menurut kalkulasi saya bisa memakan waktu sebanyak itu

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

Apakah perhitungan ini benar? akankah JVM menggunakan banyak ruang yang berdekatan ini untuk menyimpan larik int atau adakah hal lain yang perlu dipertimbangkan?

Jawaban

3 Eugene Jan 05 2021 at 01:39

Ukuran teoritis dari array tersebut adalah:

  • numberOfElementsInTheArray * 4 byte

  • 12 byte header ( int[]adalah Objek). Sebenarnya ukuran header tergantung pada flag yang Anda gunakan dan versi JVM yang Anda jalankan

  • 4 byte untuk menyimpan lengtharray

  • lapisan.

Misalnya: (Saya akan menggunakan JOL untuk ini ):

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

akan mengeluarkan:

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

Jadi itu memiliki 56 bytes:

  • 40 untuk nilainya sendiri (10 ints * 4 byte)
  • 12 untuk tajuk
  • 4 untuk panjangnya
  • 0 untuk padding

Jika Anda mengubah larik ini menjadi Integer, banyak hal berubah secara dramatis. Integeradalah Objek sehingga Anda akan menyimpan referensi di dalam larik (yang bisa berupa 4atau 8byte, tergantung pada UseCompressedOopsbendera), ditambah masing-masing Integercontoh akan membutuhkan 2 tajuk (masing Integer- masing adalah Objek).

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

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

yang akan menunjukkan:

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

Total dari 216 bytes:

  • 4 byte untuk setiap referensi (saya telah UseCompressedOopmengaktifkan), total 40 byte
  • 12 byte header dari array
  • Panjang array 4 byte
  • Bantalan 0 byte

Setiap referensi dari larik itu menunjuk ke Integer, masing-masing Objek tersebut akan memiliki 16 bytes:

  • 4 byte untuk bagian dalam yang intmereka pegang
  • Header 12 byte
  • Bantalan 0 byte
1 BasilBourque Jan 04 2021 at 15:23

Ukuran larik maksimum < Integer.MAX_VALUE

Tidak, jumlah maksimal Anda salah.

Batas jumlah elemen dalam larik di Java sedikit kurang dari Integer.MAX_VALUE(2.147.483.647), bergantung pada versi Java, OS host, dan cara Java dikompilasi. Lihat Jawaban oleh Ivan Mamontov ini tentang Pertanyaan, Mengapa saya tidak dapat membuat array dengan ukuran besar? .

Ya, rangkaian terbesar dari int≈ 8 pertunjukan

Jadi ukuran larik maksimum intkira-kira ( Integer.MAX_VALUE - 8L ) * 32Lbit yaitu 68.719.476.448 bit yaitu 8.589.934.556 oktet.

Jadi ya, sekitar 8 gigs memori. Dan ingat: ini adalah memori yang berdekatan untuk sebuah array. Begitu:

  • Mungkin ada pekerjaan yang signifikan pada bagian JVM dan OS host untuk menghasilkan larik seperti itu tergantung seberapa terfragmentasi memori pada saat itu selama runtime.
  • Jika perangkat keras host tidak memiliki cukup memori nyata, Anda akan masuk ke memori virtual di mana paging yang dihasilkan dapat menyebabkan kinerja yang buruk.

Selalu buat tes dunia nyata jika Anda benar-benar mendorong batasan ini dalam pekerjaan Anda. Dan Anda mungkin ingin mempertimbangkan implementasi alternatif Java yang dirancang untuk memori yang sangat besar, seperti Zing by Azul Systems.