Пространство, необходимое для хранения в памяти самого большого целочисленного массива
Я просматриваю алгоритм, и он хранит массив целых чисел, размер ввода динамический. Так что по моим подсчетам это может занять до
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
Это правильный расчет? будет ли JVM использовать это непрерывное пространство для хранения массива int или есть другие вещи, которые нужно учитывать?
Ответы
Теоретический размер массива будет:
numberOfElementsInTheArray * 4 байта
12 байт заголовков (
int[]
это объект). На самом деле размер заголовков зависит от используемых вами флагов и от версии JVM, в которой вы запускаете этот4 байта для хранения
length
массиваобивка.
Например: (для этого я буду использовать JOL ):
int [] x = new int[10];
for(int i=0;i<10;++i){
x[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)x).toPrintable());
выведет:
[I@7a81197dd object externals:
ADDRESS SIZE TYPE PATH VALUE
70fe45268 56 [I [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]
Итак, в нем есть 56 bytes
:
- 40 для самих значений (10 целых * 4 байта)
- 12 для заголовков
- 4 для длины
- 0 для заполнения
Если вы измените этот массив на Integer
, все кардинально изменится. Integer
является объектом, поэтому вы будете хранить ссылку внутри массива (который может быть 4
или 8
байтами, в зависимости от UseCompressedOops
флага), плюс для каждого Integer
экземпляра потребуется 2 заголовка (каждый Integer
является объектом).
Integer[] y = new Integer[10];
for(int i=0;i<10;++i){
y[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());
который покажет:
[Ljava.lang.Integer;@369f73a2d footprint:
COUNT AVG SUM DESCRIPTION
1 56 56 [Ljava.lang.Integer;
10 16 160 java.lang.Integer
11 216 (total)
Всего 216 bytes
:
- 4 байта на каждую ссылку (я
UseCompressedOop
включил), всего 40 байтов - Заголовки массива 12 байтов
- Длина массива 4 байта
- Заполнение 0 байтов
Каждая ссылка из этого массива указывает на Integer
, каждый из этих объектов будет иметь 16 bytes
:
- 4 байта для внутренней, которую
int
они держат - Заголовки 12 байтов
- Заполнение 0 байтов
Максимальный размер массива < Integer.MAX_VALUE
Нет, ваш максимум неверен.
Ограничение на количество элементов в массиве в Java немного меньше Integer.MAX_VALUE(2 147 483 647), в зависимости от версии Java, ОС хоста и способа компиляции Java. См. Ответ Ивана Мамонтова на вопрос, почему я не могу создать массив большого размера? .
Да, самый большой массив int
≈ 8 гигов
Таким образом, размер максимального массива int
будет примерно ( Integer.MAX_VALUE - 8L ) * 32L
бит, что составляет 68 719 476 448 бит, что составляет 8 589 934 556 октетов.
Так что да, около 8 гигов памяти. И помните: это непрерывная память для массива. Так:
- Для создания такого массива со стороны JVM и ОС хоста может потребоваться значительная работа, в зависимости от того, насколько фрагментирована память в данный момент во время выполнения.
- Если аппаратное обеспечение хоста не имеет достаточного количества реальной памяти, вы попадете в виртуальную память, где результирующее разбиение на страницы может привести к ужасной производительности.
Всегда проводите тесты в реальных условиях, если вы действительно выходите за эти рамки в своей работе. И вы можете рассмотреть альтернативные реализации Java, предназначенные для очень большой памяти, такие как Zing от Azul Systems.