Вопрос (сейчас) о хранении большого количества данных, которые могут быть представлены с использованием примитивных типов, таких как int
, на карте. Некоторые из ответов здесь, по моему мнению, очень вводят в заблуждение. Давайте посмотрим, почему.
Я изменил бенчмарк от trove, чтобы измерить как время работы, так и потребление памяти. Я также добавил PCJ к этому эталону, который представляет собой еще одну библиотеку коллекций для примитивных типов (я использую эту экстенсивно). «Официальный» контрольный ориентир не сравнивает IntIntMaps с Java Collection Map<Integer, Integer>
, вероятно, сохраняя Integers
, а хранение ints
не совпадает с технической точки зрения. Но пользователь может не заботиться об этой технической детали, он хочет эффективно хранить данные, представленные с помощью ints
.
Первая соответствующая часть кода:
new Operation() {
private long usedMem() {
System.gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
// trove
public void ours() {
long mem = usedMem();
TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE);
for (int i = dataset.size(); i-- > 0;) {
ours.put(i, i);
}
mem = usedMem() - mem;
System.err.println("trove " + mem + " bytes");
ours.clear();
}
public void pcj() {
long mem = usedMem();
IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE);
for (int i = dataset.size(); i-- > 0;) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("pcj " + mem + " bytes");
map.clear();
}
// java collections
public void theirs() {
long mem = usedMem();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE);
for (int i = dataset.size(); i-- > 0;) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("java " + mem + " bytes");
map.clear();
}
Я предполагаю, что данные поступают в качестве примитивного ints
, который кажется здоровым. Но это подразумевает штраф за время исполнения для java util, из-за автоматического бокса, который не обязательно для каркасов примитивных коллекций.
Результаты среды выполнения (без gc()
звонков, конечно) на WinXP, jdk1.6.0_10:
100000 put operations 100000 contains operations
java collections 1938 ms 203 ms
trove 234 ms 125 ms
pcj 516 ms 94 ms
Хотя это может показаться уже резким, это не причина, чтобы использовать такую структуру.
Причина - производительность памяти. Результаты для карты, содержащей 100000 int
записей:
java collections oscillates between 6644536 and 7168840 bytes
trove 1853296 bytes
pcj 1866112 bytes
Java Collections необходим более чем три раза памяти по сравнению с примитивными рамками сбора. То есть вы можете хранить в три раза больше данных в памяти, не прибегая к дискам IO, что снижает производительность во время выполнения по величинам. И это имеет значение. Прочтите highscalability, чтобы узнать, почему.
По моему опыту высокое потребление памяти - это самая большая проблема с производительностью с Java, что, конечно же, приводит к ухудшению производительности во время выполнения. Примитивные схемы сбора данных могут действительно помочь здесь.
So: Нет, java.util не является ответом. И «добавление функциональности» в коллекции Java не является вопросом, когда вы спрашиваете об эффективности. Также современные коллекции JDK делают не «вытесняют даже специализированные коллекции Trove».
Отказ от ответственности: Тест здесь далеко не полный, и он не идеален. Он предназначен для того, чтобы довести дело до конца, что я испытал во многих проектах. Примитивные коллекции достаточно полезны, чтобы терпеть fishy API - , если вы работаете с большим количеством данных.
Каковы ключи и значения в этой таблице? Если они не примитивы, что не так с обычным HashMap и т. Д.? –
Для очень большой карты вам может понадобиться реализация зондирования или даже встроенная таблица базы данных. –
Интересно, я не вижу упоминания о Кольте, который впоследствии был включен в Махут. – smartnut007