/**
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rx.internal;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
/**
* Benchmark typical atomic operations on volatile fields and AtomicXYZ classes.
* <p>
* gradlew benchmarks "-Pjmh=-f 1 -tu s -bm thrpt -wi 5 -i 5 -r 1 .*AtomicPerf.*"
* <p>
* gradlew benchmarks "-Pjmh=-f 1 -tu ns -bm avgt -wi 5 -i 5 -r 1 .*AtomicPerf.*"
*/
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public class AtomicPerf {
@State(Scope.Thread)
public static class Times {
@Param({ "1", "1000", "1000000" })
public int times;
}
@State(Scope.Thread)
public static class VolatileIntState {
public volatile int value;
}
@State(Scope.Thread)
public static class VolatileLongState {
public volatile long value;
}
@State(Scope.Thread)
public static class VolatileIntFieldState {
public volatile int value;
public static final AtomicIntegerFieldUpdater<VolatileIntFieldState> UPDATER
= AtomicIntegerFieldUpdater.newUpdater(VolatileIntFieldState.class, "value");
}
@State(Scope.Thread)
public static class VolatileLongFieldState {
public volatile long value;
public static final AtomicLongFieldUpdater<VolatileLongFieldState> UPDATER
= AtomicLongFieldUpdater.newUpdater(VolatileLongFieldState.class, "value");
}
@State(Scope.Thread)
public static class AtomicIntState {
public final AtomicInteger value = new AtomicInteger();
}
@State(Scope.Thread)
public static class AtomicLongState {
public final AtomicLong value = new AtomicLong();
}
// -----------------------------------------------------------------------------------
@Benchmark
public void volatileIntRead(VolatileIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value);
}
}
@Benchmark
public void volatileLongRead(VolatileLongState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value);
}
}
@Benchmark
public void volatileIntWrite(VolatileIntState state, Times repeat) {
for (int i = 0; i < repeat.times; i++) {
state.value = 1;
}
}
@Benchmark
public void volatileLongWrite(VolatileLongState state, Times repeat) {
for (int i = 0; i < repeat.times; i++) {
state.value = 1L;
}
}
// -------------------------------------------------------------
@Benchmark
public void atomicIntIncrementAndGet(AtomicIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.incrementAndGet());
}
}
@Benchmark
public void atomicIntGetAndIncrement(AtomicIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.getAndIncrement());
}
}
@Benchmark
public void atomicLongIncrementAndGet(AtomicLongState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.incrementAndGet());
}
}
@Benchmark
public void atomicLongGetAndIncrement(AtomicLongState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.getAndIncrement());
}
}
@Benchmark
public void atomicIntLazySet(AtomicIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
state.value.lazySet(1);
}
}
@Benchmark
public void atomicLongLazySet(AtomicLongState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
state.value.lazySet(1L);
}
}
@Benchmark
public void atomicIntCASSuccess(AtomicIntState state, Times repeat, Blackhole bh) {
state.value.set(0);
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.compareAndSet(i, i + 1));
}
}
@Benchmark
public void atomicLongCASSuccess(AtomicLongState state, Times repeat, Blackhole bh) {
state.value.set(0L);
for (long i = 0; i < repeat.times; i++) {
bh.consume(state.value.compareAndSet(i, i + 1));
}
}
@Benchmark
public void atomicIntCASCheckSuccess(AtomicIntState state, Times repeat, Blackhole bh) {
state.value.set(0);
for (int i = 0; i < repeat.times; i++) {
if (state.value.get() == i) {
bh.consume(state.value.compareAndSet(i, i + 1));
}
}
}
@Benchmark
public void atomicLongCASCheckSuccess(AtomicLongState state, Times repeat, Blackhole bh) {
state.value.set(0L);
for (long i = 0; i < repeat.times; i++) {
if (state.value.get() == i) {
bh.consume(state.value.compareAndSet(i, i + 1));
}
}
}
@Benchmark
public void atomicIntCASFailure(AtomicIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.compareAndSet(1, 2));
}
}
@Benchmark
public void atomicLongCASFailure(AtomicLongState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.compareAndSet(1L, 2L));
}
}
@Benchmark
public void atomicIntCASCheckFailure(AtomicIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
if (state.value.get() == 1) {
bh.consume(state.value.compareAndSet(1, 2));
}
}
}
@Benchmark
public void atomicLongCASCheckFailure(AtomicLongState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
if (state.value.get() == 1L) {
bh.consume(state.value.compareAndSet(1L, 2L));
}
}
}
// ----------------------------------
@Benchmark
public void atomicIntFieldIncrementAndGet(VolatileIntFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileIntFieldState.UPDATER.incrementAndGet(state));
}
}
@Benchmark
public void atomicIntFieldGetAndIncrement(VolatileIntFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileIntFieldState.UPDATER.getAndIncrement(state));
}
}
@Benchmark
public void atomicLongFieldIncrementAndGet(VolatileLongFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileLongFieldState.UPDATER.incrementAndGet(state));
}
}
@Benchmark
public void atomicLongFieldGetAndIncrement(VolatileLongFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileLongFieldState.UPDATER.getAndIncrement(state));
}
}
@Benchmark
public void atomicIntFieldLazySet(VolatileIntFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
VolatileIntFieldState.UPDATER.lazySet(state, 1);
}
}
@Benchmark
public void atomicLongFieldLazySet(VolatileLongFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
VolatileLongFieldState.UPDATER.lazySet(state, 1L);
}
}
@Benchmark
public void atomicIntFieldCASSuccess(VolatileIntFieldState state, Times repeat, Blackhole bh) {
state.value = 0;
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileIntFieldState.UPDATER.compareAndSet(state, i, i + 1));
}
}
@Benchmark
public void atomicLongFieldCASSuccess(VolatileLongFieldState state, Times repeat, Blackhole bh) {
state.value = 0L;
for (long i = 0; i < repeat.times; i++) {
bh.consume(VolatileLongFieldState.UPDATER.compareAndSet(state, i, i + 1));
}
}
@Benchmark
public void atomicIntFieldCASFailure(VolatileIntFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileIntFieldState.UPDATER.compareAndSet(state, 1, 2));
}
}
@Benchmark
public void atomicLongFieldCASFailure(VolatileLongFieldState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(VolatileLongFieldState.UPDATER.compareAndSet(state, 1L, 2L));
}
}
@Benchmark
public void atomicIntGetAndSet(AtomicIntState state, Times repeat, Blackhole bh) {
for (int i = 0; i < repeat.times; i++) {
bh.consume(state.value.getAndSet(i));
}
}
@Benchmark
public void atomicLongGetAndSet(AtomicLongState state, Times repeat, Blackhole bh) {
for (long i = 0; i < repeat.times; i++) {
bh.consume(state.value.getAndSet(i));
}
}
}