Инициализация ConcurrentHashMap - PullRequest
0 голосов
/ 11 января 2019

Мы используем ниже ConcurrentHashMap в качестве кэша в нашем многопоточном приложении.

private static Map<String, TransactionPriceItemDetailSummaryVO> pritmSummaryMap = new ConcurrentHashMap<String, TransactionPriceItemDetailSummaryVO>();

Мы создаем 130 потоков , которые обращаются к этой карте и обновляют ее.

Окончательный размер карты составляет около 100 миллионов (Объекты).

Я прочитал в Интернете, что нам нужно указать параметры для ConcurrentHasMap, чтобы улучшить его производительность.

Кто-нибудь может подсказать, как мы можем рассчитать параметры для нашего случая?

Кроме того, лучше ли вызывать clear() на этой карте, чтобы освободить память?

Ответы [ 4 ]

0 голосов
/ 11 января 2019

Вы можете настроить карту с помощью следующего конструктора:

ConcurrentHashMap<K,V>(initialCapacity, loadFactor, concurrencyLevel).

initialCapacity: Несмотря на то, что вы упомянули, что вы будете вставлять 100 миллионов объектов, вы собираетесь оставить их на карте? или это все равно что добавлять и удалять объекты? если вы собираетесь сохранить все из них, а не удалять их, имеет смысл сохранить это значение как 110_000_000, предложенное Bohemian, в противном случае вы должны сохранить его в качестве размера карты appx avg в любой данный момент времени.

loadFactor: более высокое значение коэффициента загрузки уменьшает объем пространства, но увеличивает стоимость поиска. Это означает, что он оказывает существенное влияние на get и put, поскольку оба эти метода выполняют поиск внутри. По умолчанию это 0.75, который обычно считается хорошим компромиссом между использованием пространства и временем поиска.

concurrencyLevel: предполагаемое количество одновременно обновляемых потоков. В этом случае вы упомянули номер 130

Приведенные выше значения могут быть дополнительно детализированы путем анализа при вызове clear() для удаления всех элементов.

0 голосов
/ 11 января 2019

С java doc : В идеале, вы должны выбрать значение, чтобы вместить столько потоков, сколько когда-либо будет одновременно изменяться таблица. Поскольку вы говорите

... 130 Тем, которые обращаются к этой карте и обновляют ее

тогда вы должны использовать

new ConcurrentHashMap<String, TransactionPriceItemDetailSummaryVO>(130)

И, как говорит @Bohemian, установите большее значение, чтобы избежать изменения размера. Звоните только если вам не нужен контент.

0 голосов
/ 11 января 2019

При таком большом количестве записей и потоков вы можете помочь реализации работать лучше, сообщив ей ожидаемый размер такой структуры через конструктор :

new ConcurrentHashMap<>(110_000_000, 10, 130);

Поэкспериментируйте с разными числами, чтобы найти, что работает.

Обратите внимание, что с таким количеством элементов вы получите высокий уровень коллизий хешей. Подумайте об использовании вложенных карт на основе разных ключей, чтобы на каждой карте было меньше записей, скажем, под 1M.

0 голосов
/ 11 января 2019

100 миллионов объектов на карте!

IMO, иметь столько объектов на статической карте никогда не будет хорошей идеей. Кроме того, это увеличивает объем используемой памяти Java, поскольку карта будет занимать так много памяти. Вы можете часто сталкиваться с ошибками нехватки памяти на сервере приложений, и дамп всегда будет иметь java.util.Map (за которым следует бесполезный хэш-код) каждый раз вверху.

Поверь мне, ты не хочешь видеть это трудным путем. Кроме того, когда к 130 потокам обращаются и кто знает, что ваше приложение может даже содержать более 200 миллионов объектов завтра, 300 миллионов - послезавтра! Всегда имейте в виду, что может вызвать это сено!

Предложение : Вы можете продолжить сериализацию (преобразовав в JSON?) TransactionPriceItemDetailSummaryVO и сохранить ее в Redis. Чувствуете некоторую масштабируемость? Просто добавьте оборудование на свой сервер Redis!

Кроме того, у Redis есть много политик истечения срока действия (ttl, это прекрасно!)

...