2012-06-19 6 views
10

Знает ли кто-то, что является издержками памяти ConcurrentHashMap (по сравнению с «классическим» HashMap)?Накладные расходы ConcurrentHashMap

  • При строительстве?
  • При установке элемента?
+0

Не имеет смысла создавать большое количество ConcurrentHashMap, поскольку у вас есть только ограниченное количество ядер. Накладные расходы небольшого количества CHM, вероятно, будут меньше 1 цента. –

+0

@PeterLawrey Я действительно не понимаю. «Бесполезно создавать большое количество ConcurrentHashMap», так что? У них все еще есть накладные расходы. Кроме того, даже если в то же время явно странно иметь много CHM, можно легко представить, что объекты с короткими живыми существами создают параллельную карту хеша при их построении (скажем, оператор объединения в программном обеспечении, ориентированном на БД?). – Maxime

+0

Причина, по которой вы можете использовать параллельные коллекции, состоит в том, что у вас больше ядер, чем у коллекций. Если у вас много других коллекций, чем ядер, маловероятно, что у вас будет одновременный доступ. –

ответ

6

Если вы используете следующее с -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 центов.

+0

Насколько надежным является измерение использования памяти? – assylias

+0

Можете ли вы объяснить смысл использования локальных распределений потоков? Благодаря! – assylias

+0

Это может быть иначе на Java 5 или других JVM, чем HotSpot или OpenJDK, но я бы удивился, если он значительно отличается. Разница может быть меньше на 32-битных JVM. –

2

Я действительно не понимаю предпосылки вопроса - либо вам нужен параллелизм, либо нет.

Однако, согласно this link, площадь памяти пустого ConcurrentHashMap составляет 1700 байт. Он рекомендует использовать ConcurrentHashMap, если у вас есть несколько потоков, которым нужен доступ для чтения/записи, но Hashtable, если у вас много потоков, которым необходим доступ на чтение, кроме одного с записью.

+0

Ссылка слишком старая, чтобы быть релевантной. Действительно, эта статья была опубликована (28.04.2012) перед Java 7, и реализация, вероятно, изменилась. Кроме того, ваш ответ является неполным, так как я также прошу ввести его (есть ли он). – Maxime

+2

@Maxime Реализация, вероятно, не так сильно изменилась, но в любом случае описывает метод, который они использовали для поиска данных. Немного исследований показывает, что никто еще этого не сделал. – purtip31

4

ConcurrentHashMap не использует значительно больше памяти, чем HashMap, как при строительстве, так и при вставке.

В Intialization

ConcurrentHashMap использует почти такой же объем памяти, как HashMap, может быть немного больше за пару дополнительных переменных и замков бухгалтерского учета.

Во время инициализации ConcurrentHashMap создает 16 сегментов для хранения значений ключа, каждый сегмент эквивалентен HashMap.

Основная емкость/размер каждого сегмента составляет 1/16 от общей начальной емкости. Таким образом, по существу, ConcurrentHashMap создает 16 маленьких HashMaps, эквивалентных одному HashMap. Каждый сегмент имеет собственную блокировку и пару переменных бухгалтерского учета (счетчик, порог и т. Д.), Это дополнительные издержки памяти.

Вы можете контролировать количество сегментов, созданных ConcurrentHashMap путем передачи соответствующего значения для concurrencyLevel параметра в ConcurrentHashMap. Чем меньше это значение, тем меньше места будет использовано, но больше конфликтов, когда большое количество потоков обновит карту. Чем выше это значение, тем больше будет создано сегментов, но производительность параллельных обновлений будет быстрее. Примечание. Значительно более высокое значение для параметра concurrencyLevel влияет на пространство и время.

Эти небольшие накладные расходы в памяти - это то, что разработчик готов принять в обмен на параллелизм.

при вставке

Когда Сегменты наполняются, будет увеличен размер этого сегмента. Политика увеличения размера аналогична политике HashMap. параметр loadfactor определяет, когда следует увеличить размер сегмента. Обратите внимание только на то, что сегмент, который будет заполнен, будет увеличен.Опять же, накладные расходы памяти почти такие же, как у HashMap.

В целом, ConcurrentHashMap не использует значительно больше памяти, чем HashMap, но его действительно сложно измерить каждый дополнительный байт, используемый ConcurrentHashMap.

 Смежные вопросы

  • Нет связанных вопросов^_^