性能有坑 | 慎用 Java 8 ConcurrentHashMap 的 computeIfAbsent

38 阅读1分钟
package ftf;

import org.openjdk.jmh.annotations.*;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Fork(3)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 3, time = 5)
@Threads(16)
@State(Scope.Benchmark)
public class ConcurrentHashMapBenchmark {

    private static final String KEY = "key";

    private static final Object VALUE = new Object();

    private final Map<String, Object> concurrentMap = new ConcurrentHashMap<>(1, 1);

    @Setup(Level.Iteration)
    public void setup() {
        concurrentMap.clear();
    }
    
    @Benchmark
    public Object benchGetBeforeComputeIfAbsent() {
        Object result = concurrentMap.get(KEY);
        if (null == result) {
            result = concurrentMap.computeIfAbsent(KEY, __ -> VALUE);
        }
        return result;
    }

    @Benchmark
    public Object benchComputeIfAbsent() {
        return concurrentMap.computeIfAbsent(KEY, __ -> VALUE);
    }
}

<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.23</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.23</version>
</dependency>

jhm性能对比 发现benchComputeIfAbsent 慢了一个数量级别。

image.png