Java: ConcurrencyLevel value for ConcurrentHashMap

Is there some optimal value for ConcurrencyLevel beyond which the performance of the ConcurrentHashMap starts to deteriorate?

If so, what is this value and what is the reason for the decline in performance? (this question concludes the attempt to find out any practical limitations that ConcurrentHashMap may have).

+4
source share
3 answers

Javadoc offers a fairly detailed guide:

The valid concurrency among update operations is controlled by the optional concurrencyLevel constructor argument (default 16), which is used as a hint for the internal size.

The table is internally partitioned to try to allow the specified number of concurrent updates without competition. Since the placement in the hash tables is essentially random, the actual concurrency will be different. Ideally, you should choose a value to accommodate as many threads as you ever change a table at one time. Using significantly higher values ​​than you need can waste space and time, and significantly lower values ​​can lead to conflict with the stream. But revaluations and underestimations in order of magnitude usually do not have a noticeable effect. The value of one is appropriate when it is known that only one thread will change, and all the others will only read.

To summarize: the optimal value depends on the number of expected simultaneous updates. A value in order of magnitude should work well. Values ​​outside this range are expected to result in poor performance.

+4
source

You must ask yourself two questions.

  • how much cpus do i have?
  • what percentage of the time will have access to a useful program for the same card?

The first question indicates the maximum number of threads that can immediately access the map. You can have 10,000 threads, but if you have only 4 processors, at most 4 will be launched.

The second question tells you that any of these threads will access the map and do something useful. You can optimize the card to do something useless (for example, a micro benchmark), but there is no exact setting for this IMHO. Let's say you have a useful program that uses a map a lot. This can spend 90% of the time doing something else, for example. IO, accessing other cards, creating keys or values, doing something with the values ​​that it receives from the card.

Say that you spend 10% of your time accessing the card on a machine with 4 processors. This means that on average you will get access to the map in 0.4 flows on average. (Or one thread about 40% of the time). In this case, concurrency level 1-4 is fine.

In any case, if the concurrency level is higher than the number of processors that you have, it will probably be superfluous, even for the micro benchmark.

+4
source

In Java 8, the ConcurrentHashMap constructor parameter for concurrencyLevel is not effectively used and remains mainly for backward compatibility. The implementation was rewritten to use the first node inside each hash bin as a lock for this bin, and not a fixed number of segments / bands, as it was in previous versions.

In short, starting in Java 8, don't worry about setting the concurrencyLevel parameter if you set a positive (non-zero, non-negative) value for the API contract.

+1
source

Source: https://habr.com/ru/post/1398602/


All Articles