【问题标题】:ConcurrentHashMap size() performanceConcurrentHashMap size() 性能
【发布时间】:2014-10-13 13:45:41
【问题描述】:

ConcurrentHashMap size()的运行时间表现如何?查看源代码(这是 Java7)我无法弄清楚,而且我没有在文档中看到它的讨论。

这里是代码

 public int size() {
        // Try a few times to get accurate count. On failure due to
        // continuous async changes in table, resort to locking.
        final Segment<K,V>[] segments = this.segments;
        int size;
        boolean overflow; // true if size overflows 32 bits
        long sum;         // sum of modCounts
        long last = 0L;   // previous sum
        int retries = -1; // first iteration isn't retry
        try {
            for (;;) {
                if (retries++ == RETRIES_BEFORE_LOCK) {
                    for (int j = 0; j < segments.length; ++j)
                        ensureSegment(j).lock(); // force creation
                }
                sum = 0L;
                size = 0;
                overflow = false;
                for (int j = 0; j < segments.length; ++j) {
                    Segment<K,V> seg = segmentAt(segments, j);
                    if (seg != null) {
                        sum += seg.modCount;
                        int c = seg.count;
                        if (c < 0 || (size += c) < 0)
                            overflow = true;
                    }
                }
                if (sum == last)
                    break;
                last = sum;
            }
        } finally {
            if (retries > RETRIES_BEFORE_LOCK) {
                for (int j = 0; j < segments.length; ++j)
                    segmentAt(segments, j).unlock();
            }
        }
        return overflow ? Integer.MAX_VALUE : size;
    }

【问题讨论】:

  • 如何针对您的目标场景进行基准测试?这肯定取决于很多因素,尤其是竞争程度。
  • 我不想猜。我需要弄清楚我是否可以访问每个请求的大小,或者是否应该只在计时器上完成。
  • 所以你认为基准测试会导致猜测?显然,您不会在这里得到“权威答案”,因为如果有的话,它就会在 Javadoc 中。
  • 我在找这个方法的理论运行时间。 Java 中的许多方法都有摊销的运行时限制,也有例外。为什么这有什么不同?
  • 而且该数据的来源在所有情况下都是相应类的Javadoc,不是吗?因此,您只能进行猜测,而基准测试无疑是对扶手椅猜测的改进。另请注意,这些理论时间仅适用于单线程设置。你会关心并发映射的单线程性能吗?

标签: java performance concurrenthashmap


【解决方案1】:

嗯,我对代码的阅读是复杂度是O(1)

首先,如果您查看其余代码,您将看到 segments.length 在创建地图时依赖于 concurrencyLevel 的值。重新分配地图时它不会改变。

因此,在无竞争的情况下,很容易看到for(;;) 循环内的内容将被执行两次,并且内部循环的迭代次数为segments.length;即这是O(1) 整体。

在竞争的情况下,性能会更差,因为for(;;) 循环可能会被执行多次。但我仍然认为相对于地图大小N,复杂度将是O(1)


但话虽如此,看起来size() 是一个昂贵的操作,如果争用足够大,算法不得不回退到锁定整个地图,这将是一个并发瓶颈;即retries 达到RETRIES_BEFORE_LOCK(我查看的版本中为 2)。

【讨论】:

    猜你喜欢
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    相关资源
    最近更新 更多