diff --git a/internal-api/src/jmh/java/datadog/trace/util/AtomicsBenchmark.java b/internal-api/src/jmh/java/datadog/trace/util/AtomicsBenchmark.java new file mode 100644 index 00000000000..d2c950fb786 --- /dev/null +++ b/internal-api/src/jmh/java/datadog/trace/util/AtomicsBenchmark.java @@ -0,0 +1,161 @@ +package datadog.trace.util; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.function.Supplier; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +/** + *
Java 17 - MacBook M1 - 8 threads
+ * Benchmark Mode Cnt Score Error Units
+ * AtomicsBenchmark.atomicFieldUpdater_construction thrpt 6 4442811623.924 ± 293568588.782 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_construction:gc.alloc.rate.norm thrpt 6 16.000 ± 0.001 B/op
+
+ * AtomicsBenchmark.atomicFieldUpdater_get thrpt 6 1849238178.083 ± 29719143.488 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_get:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁶ B/op
+
+ * AtomicsBenchmark.atomicFieldUpdater_getVolatile thrpt 6 1814698391.230 ± 54378746.492 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_getVolatile:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁶ B/op
+
+ * AtomicsBenchmark.atomicFieldUpdater_incrementAndGet thrpt 6 15871753.651 ± 432451.444 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_incrementAndGet:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁴ B/op
+
+ * AtomicsBenchmark.atomic_construction thrpt 6 2532095943.171 ± 87644803.894 ops/s
+ * AtomicsBenchmark.atomic_construction:gc.alloc.rate.norm thrpt 6 32.000 ± 0.001 B/op
+
+ * AtomicsBenchmark.atomic_incrementAndGet thrpt 6 16416635.546 ± 751137.083 ops/s
+ * AtomicsBenchmark.atomic_incrementAndGet:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁴ B/op
+
+ * AtomicsBenchmark.atomic_read thrpt 6 1943297600.062 ± 43802387.143 ops/s
+ * AtomicsBenchmark.atomic_read:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁶ B/op
+ */
+@Fork(2)
+@Warmup(iterations=2)
+@Measurement(iterations=3)
+@Threads(8)
+public class AtomicsBenchmark {
+ static int SIZE = 32;
+
+ static final class AtomicHolder {
+ final AtomicInteger atomic;
+
+ AtomicHolder(int num) {
+ this.atomic = new AtomicInteger(num);
+ }
+
+ int get() {
+ return this.atomic.get();
+ }
+
+ int incrementAndGet() {
+ return this.atomic.incrementAndGet();
+ }
+ }
+
+ static final class FieldHolder {
+ static final AtomicIntegerFieldUpdater AFU_FIELD = AtomicIntegerFieldUpdater.newUpdater(FieldHolder.class, "field");
+
+ volatile int field;
+
+ FieldHolder(int num) {
+ this.field = num;
+ }
+
+ int getVolatile() {
+ return this.field;
+ }
+
+ int get() {
+ return AFU_FIELD.get(this);
+ }
+
+ int incrementAndGet() {
+ return AFU_FIELD.incrementAndGet(this);
+ }
+ }
+
+ static final AtomicHolder[] atomicHolders = init(() -> {
+ AtomicHolder[] holders = new AtomicHolder[SIZE];
+ for ( int i = 0; i < holders.length; ++i ) {
+ holders[i] = new AtomicHolder(i * 2);
+ }
+ return holders;
+ });
+
+ static final FieldHolder[] fieldHolders = init(() -> {
+ FieldHolder[] holders = new FieldHolder[SIZE];
+ for ( int i = 0; i < holders.length; ++i ) {
+ holders[i] = new FieldHolder(i * 2);
+ }
+ return holders;
+ });
+
+ static final T init(Supplier supplier) {
+ return supplier.get();
+ }
+
+ static int sharedLookupIndex = 0;
+
+ static T next(T[] holders) {
+ int localIndex = ++sharedLookupIndex;
+ if ( localIndex >= holders.length ) {
+ sharedLookupIndex = localIndex = 0;
+ }
+ return holders[localIndex];
+ }
+
+ @Benchmark
+ public Object atomic_construction() {
+ return new AtomicHolder(0);
+ }
+
+ @Benchmark
+ public int atomic_incrementAndGet() {
+ return next(atomicHolders).incrementAndGet();
+ }
+
+ @Benchmark
+ public Object atomic_read() {
+ return next(atomicHolders).get();
+ }
+
+ @Benchmark
+ public Object atomicFieldUpdater_construction() {
+ return new FieldHolder(0);
+ }
+
+ @Benchmark
+ public Object atomicFieldUpdater_getVolatile() {
+ return next(fieldHolders).getVolatile();
+ }
+
+ @Benchmark
+ public Object atomicFieldUpdater_get() {
+ return next(fieldHolders).get();
+ }
+
+ @Benchmark
+ public int atomicFieldUpdater_incrementAndGet() {
+ return next(fieldHolders).incrementAndGet();
+ }
+}