2015-11-24 8 views
1

У меня есть приложение с низкой пропускной способностью с высокой пропускной способностью (3000 запросов/сек, 100 мс на запрос), и мы активно используем Java 8 ConcurrentHashMap для выполнения поиска. Обычно эти карты обновляются одним фоновым потоком и несколькими потоками, считанными с этих карт.Java 8 Concurrent Hash Map получить производительность/альтернативу

Я вижу узкое место в производительности, и при профилировании я нахожу ConcurrentHashMap.get как точку доступа и большую часть времени.

Я другой случай, я вижу ConcurrentHashMap.computeIfAbsent являюсь точкой доступа, хотя отображение-функция имеет очень малую задержку и профиль показывает computeIfAbsent расходов на 90% время, выполняющиеся себя, и очень меньше времени при выполнении отображения-функции.

Вопрос в том, можно ли улучшить производительность? У меня около 80 потоков одновременно с CHM.

+0

Используется ли ваш файл hasmap для чтения значений, записывая значения, оба? Очень сложно помочь вам, если у нас больше нет информации о самом алгоритме. –

+0

Вы должны [prescreen] (https://github.com/ben-manes/caffeine/wiki/Benchmarks) 'computeIfAbsent' оптимистичным' get', чтобы избежать штрафа за блокировку при чтении. –

+0

@GuillaumeF. для (чтение при 3000 Rps), и запись будет примерно 100 кпс. Ben Manes: можете ли вы рассказать о –

ответ

1

У меня около 80 потоков, одновременно читающих CHM.

Простейшие вещи, чтобы сделать это

  • , если у вас есть процесс работы процессора, не более активные потоки, чем у процессоров, в противном случае это будет только добавить накладные расходы, и если эти нити провести блокировка пока не работает, потому что у вас слишком много потоков, это действительно не поможет.
  • увеличить количество разделов. Вы хотите иметь по крайней мере 4 раза количество сегментов/разделов, и у вас есть потоки, обращающиеся к одной карте. Тем не менее, вы получите странное поведение в CHM, если вы получите доступ к нему с более чем 40 потоками из-за того, как работает когерентность кэша. Я предлагаю использовать более эффективную структуру данных для более высокой степени параллелизма. В Java 8 concurrencyLevel является подсказкой, но лучше, чем оставить исходный размер по умолчанию 16.
  • не тратьте столько времени на CHM. Найдите способ сделать полезную работу, не затрагивая общий ресурс, и ваши потоки будут работать намного эффективнее.

Если у вас есть какие-либо задержки, вы можете видеть в системе с низкой задержкой, у вас есть проблема ИМХО.

+1

'вы получите странное поведение в CHM, если вы получите доступ к нему с более чем 40 потоками. Можете ли вы рассказать об этом? Каким будет поведение? Ведь CHM предназначен для одновременного доступа, не так ли? Также я не вижу никаких проблем с огромным количеством потоков * чтения *, если не существует много писателей. –

+0

@ Светлин Зарева хорошая точка, чтение не должно быть проблемой. В системах с большим количеством процессоров я видел проблемы с масштабируемостью с CHM, когда у вас более 40 активных потоков, попавших в один и тот же CHM. Скорее всего, это аппаратное обеспечение, а не проблема с программным обеспечением, так как машина использует несколько сокетов. Когда у нас может быть 40 потоков на одном сокете, я подозреваю, что проблема исчезнет. –

+0

Спасибо @Peter !! QQ: Еще одна вещь, которую я нашел, - это использование CHM с ключом как java.util.TimeZone 'get' занимает больше времени, чем vs, используя CHM со строкой в ​​качестве ключа. Любые мысли по этому поводу? Связано ли это с столкновениями? –

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

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