Java: значение ConcurrencyLevel для ConcurrentHashMap - PullRequest
4 голосов
/ 27 февраля 2012

Есть ли какое-то оптимальное значение для ConcurrencyLevel, после которого производительность ConcurrentHashMap начинает снижаться?

Если да, каково это значение и в чем причина снижения производительности?(этот вопрос связан с попыткой выяснить какие-либо практические ограничения, которые могут иметь ConcurrentHashMap).

Ответы [ 3 ]

4 голосов
/ 27 февраля 2012

Вы должны задать себе два вопроса

  • сколько у меня процессоров?
  • в какой процент времени полезная программа будет обращаться к той же карте?

В первом вопросе указано максимальное количество потоков, которые могут получить доступ к карте одновременно. У вас может быть 10000 потоков, но если у вас только 4 процессора, максимум 4 будут запущены одновременно.

Второй вопрос говорит вам, что большинство из этих потоков будут иметь доступ к карте и делать что-то полезное. Вы можете оптимизировать карту, чтобы сделать что-то бесполезное (например, микро-тест), но нет смысла настраивать это ИМХО. Скажем, у вас есть полезная программа, которая много использует карту. Это может быть 90% времени, занимаясь чем-то другим, например IO, доступ к другим картам, создание ключей или значений, выполнение действий со значениями, полученными с карты.

Допустим, вы тратите 10% времени на доступ к карте на машине с 4 процессорами. Это означает, что в среднем вы будете получать доступ к карте в среднем в 0,4 потоках. (Или один поток примерно в 40% случаев). В этом случае уровень параллелизма 1-4 подходит.

В любом случае, повышение уровня параллелизма по сравнению с числом имеющихся у вас процессоров может оказаться ненужным даже для микропроцессора.

4 голосов
/ 27 февраля 2012

Javadoc предлагает довольно подробное руководство:

Допустимый параллелизм среди операций обновления определяется необязательным аргументом конструктора concurrencyLevel (по умолчанию 16), который используется какподсказка для внутреннего определения размера.

Таблица разбита на внутренние разделы, чтобы попытаться разрешить указанное количество одновременных обновлений без конфликтов.Поскольку размещение в хеш-таблицах по существу случайное, фактический параллелизм будет отличаться.В идеале вы должны выбрать значение, чтобы вместить столько потоков, сколько когда-либо одновременно изменят таблицу.Использование значительно более высокого значения, чем вам нужно, может тратить пространство и время, а значительно более низкое значение может привести к конфликту потоков.Но завышения и недооценки в пределах порядка величины обычно не оказывают заметного влияния.Значение 1 подходит, когда известно, что будет изменен только один поток, а все остальные будут только читать.

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

1 голос
/ 25 апреля 2017

Начиная с Java 8, параметр конструктора ConcurrentHashMap для concurrencyLevel практически не используется и остается в основном для обратной совместимости.Реализация была переписана для использования первого узла в каждом хэш-бине в качестве блокировки для этого бина, а не фиксированного числа сегментов / полос, как было в предыдущих версиях.

Короче говоря, начиная сJava 8, не беспокойтесь об установке параметра concurrencyLevel, если в контракте API установлено положительное (ненулевое, неотрицательное) значение.

...