Знает ли кто-то, что является издержками памяти ConcurrentHashMap (по сравнению с «классическим» HashMap)?Накладные расходы ConcurrentHashMap
- При строительстве?
- При установке элемента?
Знает ли кто-то, что является издержками памяти ConcurrentHashMap (по сравнению с «классическим» HashMap)?Накладные расходы ConcurrentHashMap
Если вы используете следующее с -XX:-UseTLAB -XX:NewSize=900m -mx1g
на 64-разрядной JVM.
public static void main(String... args) throws NoSuchMethodException, IllegalAccessException {
for (int i = 0; i < 4; i++) {
long used1 = usedMemory();
populate(new HashMap());
long used2 = usedMemory();
populate(new ConcurrentHashMap());
long used3 = usedMemory();
System.out.println("The ratio of used memory is " + (double) (used3 - used2)/(used2 - used1));
System.out.println("For an extra " + ((used3 - used2) - (used2 - used1))/1000000 + " bytes per entry was used.");
}
}
private static void populate(Map map) {
for (Integer i = 0; i < 1000000; i++)
map.put(i, i);
}
private static long usedMemory() {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
вы получаете с Java 6 и 7 за миллион записей.
The ratio of used memory is 1.1291128466982379
For an extra 8 bytes per entry was used.
The ratio of used memory is 1.1292086928728067
For an extra 8 bytes per entry was used.
The ratio of used memory is 1.1292086928728067
For an extra 8 bytes per entry was used.
The ratio of used memory is 1.1292086928728067
For an extra 8 bytes per entry was used.
Восемь МБ памяти стоят около 5 центов.
Насколько надежным является измерение использования памяти? – assylias
Можете ли вы объяснить смысл использования локальных распределений потоков? Благодаря! – assylias
Это может быть иначе на Java 5 или других JVM, чем HotSpot или OpenJDK, но я бы удивился, если он значительно отличается. Разница может быть меньше на 32-битных JVM. –
Я действительно не понимаю предпосылки вопроса - либо вам нужен параллелизм, либо нет.
Однако, согласно this link, площадь памяти пустого ConcurrentHashMap
составляет 1700 байт. Он рекомендует использовать ConcurrentHashMap
, если у вас есть несколько потоков, которым нужен доступ для чтения/записи, но Hashtable
, если у вас много потоков, которым необходим доступ на чтение, кроме одного с записью.
Ссылка слишком старая, чтобы быть релевантной. Действительно, эта статья была опубликована (28.04.2012) перед Java 7, и реализация, вероятно, изменилась. Кроме того, ваш ответ является неполным, так как я также прошу ввести его (есть ли он). – Maxime
@Maxime Реализация, вероятно, не так сильно изменилась, но в любом случае описывает метод, который они использовали для поиска данных. Немного исследований показывает, что никто еще этого не сделал. – purtip31
ConcurrentHashMap
не использует значительно больше памяти, чем HashMap
, как при строительстве, так и при вставке.
В Intialization
ConcurrentHashMap
использует почти такой же объем памяти, как HashMap, может быть немного больше за пару дополнительных переменных и замков бухгалтерского учета.
Во время инициализации ConcurrentHashMap
создает 16 сегментов для хранения значений ключа, каждый сегмент эквивалентен HashMap.
Основная емкость/размер каждого сегмента составляет 1/16 от общей начальной емкости. Таким образом, по существу, ConcurrentHashMap
создает 16 маленьких HashMaps, эквивалентных одному HashMap. Каждый сегмент имеет собственную блокировку и пару переменных бухгалтерского учета (счетчик, порог и т. Д.), Это дополнительные издержки памяти.
Вы можете контролировать количество сегментов, созданных ConcurrentHashMap
путем передачи соответствующего значения для concurrencyLevel параметра в ConcurrentHashMap
. Чем меньше это значение, тем меньше места будет использовано, но больше конфликтов, когда большое количество потоков обновит карту. Чем выше это значение, тем больше будет создано сегментов, но производительность параллельных обновлений будет быстрее. Примечание. Значительно более высокое значение для параметра concurrencyLevel влияет на пространство и время.
Эти небольшие накладные расходы в памяти - это то, что разработчик готов принять в обмен на параллелизм.
при вставке
Когда Сегменты наполняются, будет увеличен размер этого сегмента. Политика увеличения размера аналогична политике HashMap. параметр loadfactor определяет, когда следует увеличить размер сегмента. Обратите внимание только на то, что сегмент, который будет заполнен, будет увеличен.Опять же, накладные расходы памяти почти такие же, как у HashMap.
В целом, ConcurrentHashMap
не использует значительно больше памяти, чем HashMap
, но его действительно сложно измерить каждый дополнительный байт, используемый ConcurrentHashMap
.
Не имеет смысла создавать большое количество ConcurrentHashMap, поскольку у вас есть только ограниченное количество ядер. Накладные расходы небольшого количества CHM, вероятно, будут меньше 1 цента. –
@PeterLawrey Я действительно не понимаю. «Бесполезно создавать большое количество ConcurrentHashMap», так что? У них все еще есть накладные расходы. Кроме того, даже если в то же время явно странно иметь много CHM, можно легко представить, что объекты с короткими живыми существами создают параллельную карту хеша при их построении (скажем, оператор объединения в программном обеспечении, ориентированном на БД?). – Maxime
Причина, по которой вы можете использовать параллельные коллекции, состоит в том, что у вас больше ядер, чем у коллекций. Если у вас много других коллекций, чем ядер, маловероятно, что у вас будет одновременный доступ. –