Recently I looked at the Skywalking source code and found that there was a significant performance improvement in an atomic class data structure that doubled the efficiency of 10 lines of code, so I looked into it in detail

demand

An atomic Integer type that varies between startValue and endValue

The old atomic class

    public final int getAndIncrement(a) {
        int current;
        int next;
        do {
            current = this.value.get();
            next = current >= this.endValue ? this.startValue : current + 1;
        }
        while (!this.value.compareAndSet(current, next));

        return current;
    }
Copy the code

New atomic class

    public final int getAndIncrement(a) {
        int next;
        do {
            next = this.value.incrementAndGet();
            if (next > endValue && this.value.compareAndSet(next, startValue)) {
                returnendValue; }}while (next > endValue);

        return next - 1;
    }
Copy the code

Performance improvement

Using Junit’s Benchmark, we find that

* Benchmark Mode Cnt Score Error Units * AtomicRangeIntegerTest testNewGetAndIncrementPerformance THRPT 41474285.923 + / - 5 3595500.827 ops/s * AtomicRangeIntegerTest testOriGetAndIncrementPerformance THRPT 5 to 14199415.907 + 1697559.657 ops/sCopy the code

Ops increased from 170K to 360k performance doubled

The principle of analysis

We can see that the old code must be updated by compareAndSet every time. There are many disadvantages. 1. The new code uses the AtomicInteger class to increment each time to reduce the collision probability. The consumption of the lock will only be compareAndSet when the endValue is reached And while loops only loop once most of the time, so read the source code to improve your understanding of concurrent classes