Ruang yang dibutuhkan untuk menyimpan array bilangan bulat terbesar dalam memori
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
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 jalankan4 byte untuk menyimpan
length
arraylapisan.
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. Integer
adalah Objek sehingga Anda akan menyimpan referensi di dalam larik (yang bisa berupa 4
atau 8
byte, tergantung pada UseCompressedOops
bendera), ditambah masing-masing Integer
contoh 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
UseCompressedOop
mengaktifkan), 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
int
mereka pegang - Header 12 byte
- Bantalan 0 byte
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 int
kira-kira ( Integer.MAX_VALUE - 8L ) * 32L
bit 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.