Я знаю, что коллекции Java очень требовательны к памяти, и я сам провел тест, доказав, что 4 ГБ едва достаточно для хранения нескольких миллионов Integer
с в HashSet
.
Но что, если у меня «достаточно» памяти? Что будет с Collection.size()
?
РЕДАКТИРОВАТЬ: Решено: Collection.size()
возвращает Integer.MAX
при превышении целочисленного диапазона.
Новый вопрос: как тогда определить «реальное» количество элементов коллекции?
ПРИМЕЧАНИЕ 1: Извините, это, вероятно, вопрос "дай мне погуглить", но я действительно ничего не нашел;)
ПРИМЕЧАНИЕ 2: Насколько я понимаю, каждая целочисленная запись набора:
reference + cached_hashcode + boxed_integer_object + real_int_value
, верно?
ПРИМЕЧАНИЕ 3. Забавно, даже с JDK7 и «сжатыми указателями», когда JVM использует 2 ГБ реальной памяти, в VisualVM
.
отображается только 1,5 ГБ выделенной памяти.
Для тех, кому небезразлично:
Источники испытаний:
import java.util.*;
import java.lang.management.*;
public final class _BoxedValuesInSetMemoryConsumption {
private final static int MILLION = 1000 * 1000;
public static void main(String... args) {
Set<Integer> set = new HashSet<Integer>();
for (int i = 1;; ++i) {
if ((i % MILLION) == 0) {
int milsOfEntries = (i / MILLION);
long mbytes = ManagementFactory.getMemoryMXBean().
getHeapMemoryUsage().getUsed() / MILLION;
int ratio = (int) mbytes / milsOfEntries;
System.out.println(milsOfEntries + " mil, " + mbytes + " MB used, "
+ " ratio of bytes per entry: " + ratio);
}
set.add(i);
}
}
}
Параметры исполнения:
Протестировано с 64-разрядной версией JDK7 build 105 под OpenSuse 11.3 x64.
-XX:+UseCompressedOops -Xmx2048m
Результат вывода:
1 mil, 56 MB used, ratio of bytes per entry: 56
2 mil, 113 MB used, ratio of bytes per entry: 56
3 mil, 161 MB used, ratio of bytes per entry: 53
4 mil, 225 MB used, ratio of bytes per entry: 56
5 mil, 274 MB used, ratio of bytes per entry: 54
6 mil, 322 MB used, ratio of bytes per entry: 53
7 mil, 403 MB used, ratio of bytes per entry: 57
8 mil, 452 MB used, ratio of bytes per entry: 56
9 mil, 499 MB used, ratio of bytes per entry: 55
10 mil, 548 MB used, ratio of bytes per entry: 54
11 mil, 596 MB used, ratio of bytes per entry: 54
12 mil, 644 MB used, ratio of bytes per entry: 53
13 mil, 827 MB used, ratio of bytes per entry: 63
14 mil, 874 MB used, ratio of bytes per entry: 62
15 mil, 855 MB used, ratio of bytes per entry: 57
16 mil, 902 MB used, ratio of bytes per entry: 56
17 mil, 951 MB used, ratio of bytes per entry: 55
18 mil, 999 MB used, ratio of bytes per entry: 55
19 mil, 1047 MB used, ratio of bytes per entry: 55
20 mil, 1096 MB used, ratio of bytes per entry: 54
21 mil, 1143 MB used, ratio of bytes per entry: 54
22 mil, 1191 MB used, ratio of bytes per entry: 54
23 mil, 1239 MB used, ratio of bytes per entry: 53
24 mil, 1288 MB used, ratio of bytes per entry: 53
25 mil, 1337 MB used, ratio of bytes per entry: 53
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
В конце было использовано около 2 ГБ реальной памяти вместо отображаемых 1,3 ГБ, поэтому потребление для каждой записи даже больше , чем 53 байта.