Реализация AtomicInteger и дублирование кода

Предупреждение: вопрос немного длинный, но часть ниже разделительной линии только для любопытства.

Реализация Oracle JDK 7AtomicInteger включает в себя следующие методы:

public final int addAndGet(int delta) {
    for (;;) {
        int current = get();
        int next = current + delta;         // Only difference
        if (compareAndSet(current, next))
            return next;
    }
}

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;             // Only difference
        if (compareAndSet(current, next))
            return next;
    }
}

Кажется очевидным, что второй метод мог быть написан:

public final int incrementAndGet() {
    return addAndGet(1);
}

В этом классе есть несколько других примеров подобного дублирования кода. Я не могу придумать никаких причин для этого, кроме соображений производительности (*). И я почти уверен, что авторы провели некоторое углубленное тестирование, прежде чем остановиться на этом дизайне.

Почему (или при каких обстоятельствах) первый код будет работать лучше, чем второй?

(*) Я не удержался, но написал быстрый микро-тест. Это показывает (после JIT) систематический разрыв в 2-4% производительности в пользуaddAndGet(1) противincrementAndGet() (это по общему признанию маленький, но это очень последовательно). Я не могу объяснить этот результат, если честно ...

Выход:

incrementAndGet (): 905
addAndGet (1): 868
incrementAndGet (): 902
addAndGet (1): 863
incrementAndGet (): 891
addAndGet (1): 867
...

Код:

public static void main(String[] args) throws Exception {
    final int size = 100_000_000;
    long start, end;
    AtomicInteger ai;

    System.out.println("JVM warmup");
    for (int j = 0; j < 10; j++) {
        start = System.nanoTime();
        ai = new AtomicInteger();
        for (int i = 0; i < size / 10; i++) {
            ai.addAndGet(1);
        }
        end = System.nanoTime();
        System.out.println("addAndGet(1): " + ((end - start) / 1_000_000));
        start = System.nanoTime();
        ai = new AtomicInteger();
        for (int i = 0; i < size / 10; i++) {
            ai.incrementAndGet();
        }
        end = System.nanoTime();
        System.out.println("incrementAndGet(): " + ((end - start) / 1_000_000));
    }


    System.out.println("\nStart measuring\n");

    for (int j = 0; j < 10; j++) {
        start = System.nanoTime();
        ai = new AtomicInteger();
        for (int i = 0; i < size; i++) {
            ai.incrementAndGet();
        }
        end = System.nanoTime();
        System.out.println("incrementAndGet(): " + ((end - start) / 1_000_000));
        start = System.nanoTime();
        ai = new AtomicInteger();
        for (int i = 0; i < size; i++) {
            ai.addAndGet(1);
        }
        end = System.nanoTime();
        System.out.println("addAndGet(1): " + ((end - start) / 1_000_000));
    }
}

Ответы на вопрос(5)

Ваш ответ на вопрос