简体   繁体   English

Java:ConcurrentHashMap的ConcurrencyLevel值

[英]Java: ConcurrencyLevel value for ConcurrentHashMap

Is there some optimal value for ConcurrencyLevel beyond which ConcurrentHashMap's performance starts degrading? ConcurrencyLevel是否有一些最佳值,超出该值,ConcurrentHashMap的性能开始降低?

If yes, what's that value, and what's the reason for performance degradation? 如果是,那该值是什么,以及性能下降的原因是什么? (this question orginates from trying to find out any practical limitations that a ConcurrentHashMap may have). (这个问题源自试图找出ConcurrentHashMap可能具有的任何实际限制)。

The Javadoc offers pretty detailed guidance: Javadoc提供了非常详细的指导:

The allowed concurrency among update operations is guided by the optional concurrencyLevel constructor argument (default 16), which is used as a hint for internal sizing. 更新操作之间允许的并发性由可选的concurrencyLevel构造函数参数(缺省值16)引导,该参数用作内部大小调整的提示。

The table is internally partitioned to try to permit the indicated number of concurrent updates without contention. 该表在内部进行分区,以尝试允许指定数量的并发更新而不会发生争用。 Because placement in hash tables is essentially random, the actual concurrency will vary. 因为散列表中的放置基本上是随机的,所以实际的并发性会有所不同。 Ideally, you should choose a value to accommodate as many threads as will ever concurrently modify the table. 理想情况下,您应该选择一个值来容纳与同时修改表一样多的线程。 Using a significantly higher value than you need can waste space and time, and a significantly lower value can lead to thread contention. 使用比您需要的更高的值会浪费空间和时间,而显着更低的值可能导致线程争用。 But overestimates and underestimates within an order of magnitude do not usually have much noticeable impact. 但是,在一个数量级内过高估计和低估通常不会产生明显的影响。 A value of one is appropriate when it is known that only one thread will modify and all others will only read. 当知道只有一个线程会修改而其他所有线程只能读取时,值为1是合适的。

To summarize: the optimal value depends on the number of expected concurrent updates. 总结一下: 最佳值取决于预期的并发更新数。 A value within an order of magnitude of that should work well. 在一个数量级内的值应该很好。 Values outside that range can be expected to lead to performance degradation. 超出该范围的值可能会导致性能下降。

You have to ask yourself two questions 你必须问自己两个问题

  • how many cpus do I have? 我有多少cpus?
  • what percentage of the time will a useful program be accessing the same map? 有用程序访问同一地图的时间百分比是多少?

The first question tells you the maximum number of threads which can access the map at once. 第一个问题告诉您一次可以访问地图的最大线程数。 You can have 10000 threads, but if you have only 4 cpus, at most 4 will be running at once. 您可以拥有10000个线程,但如果您只有4个cpus,则最多只能运行4个线程。

The second question tells you the most any of those threads will be accessing the map AND doing something useful. 第二个问题告诉你,这些线程中的任何一个都将访问地图并做一些有用的事情。 You can optimise the map to do something useless (eg a micro-benchmark) but there is no point tuning for this IMHO. 您可以优化地图以做一些无用的事情(例如微基准测试),但这个恕我直言的调整没有任何意义。 Say you have a useful program which uses the map a lot. 假设您有一个有用的程序,它使用了很多地图。 It might be spending 90% of the time doing something else eg IO, accessing other maps, building keys or values, doing something with the values it gets from the map. 它可能花90%的时间做其他事情,例如IO,访问其他地图,构建键或值,使用从地图获取的值做某事。

Say you spend 10% of the time accessing a map on a machine with 4 CPUs. 假设您花费10%的时间在具有4个CPU的计算机上访问地图。 This means on average you will be accessing the map in 0.4 threads on average. 这意味着平均而言,您将平均访问0.4个线程的地图。 (Or one thread about 40% of the time) In this case a concurrency level of 1-4 is fine. (或者大约40%的时间使用一个线程)在这种情况下,1-4的并发级别就可以了。

In any case, making the concurrency level higher than the number of cpus you have is likely to be unnecessary, even for a micro-benchmark. 在任何情况下,即使对于微基准测试,使并发级别高于您拥有的cpu的数量也可能是不必要的。

As of Java 8, ConcurrentHashMap 's constructor parameter for concurrencyLevel is effectively unused , and remains primarily for backwards-compatibility. 从Java 8开始, ConcurrentHashMapconcurrencyLevel构造函数参数实际上未被使用 ,主要用于向后兼容。 The implementation was re-written to use the first node within each hash bin as the lock for that bin, rather than a fixed number of segments/stripes as was the case in earlier versions. 重新编写实现以使用每个散列箱中的第一个节点作为该bin的锁,而不是像早期版本中那样固定数量的段/条带。

In short, starting in Java 8, don't worry about setting the concurrencyLevel parameter, as long as you set a positive (non-zero, non-negative) value, per the API contract. 简而言之,从Java 8开始,只要根据API契约设置正(非零,非负)值,就不必担心设置concurrencyLevel参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM