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..b1a7f0d26c1 --- /dev/null +++ b/internal-api/src/jmh/java/datadog/trace/util/AtomicsBenchmark.java @@ -0,0 +1,172 @@ +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.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +/** + * The choice between {@link AtomicInteger} and {@link AtomicIntegerFieldUpdater} depends on the + * access pattern: + * + *
Future: {@code VarHandle} (Java 9+) is the modern replacement for
+ * AtomicIntegerFieldUpdater. It avoids the reflective field-access overhead, which should close
+ * the incrementAndGet gap with AtomicInteger while retaining the construction allocation advantage.
+ * Not available here because internal-api targets Java 8.
+ *
+ * Java 17 - MacBook M1 Pro Max - 8 threads
+ * Benchmark Mode Cnt Score Error Units
+ * AtomicsBenchmark.atomicFieldUpdater_construction thrpt 6 2215272588.708 ± 88556141.052 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_construction:gc.alloc.rate.norm thrpt 6 16.000 ± 0.001 B/op
+ *
+ * AtomicsBenchmark.atomicFieldUpdater_get thrpt 6 2174739788.040 ± 56980971.014 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_get:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁶ B/op
+ *
+ * AtomicsBenchmark.atomicFieldUpdater_getVolatile thrpt 6 2157331061.707 ± 136900932.336 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_getVolatile:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁶ B/op
+ *
+ * AtomicsBenchmark.atomicFieldUpdater_incrementAndGet thrpt 6 90785783.320 ± 7650837.727 ops/s
+ * AtomicsBenchmark.atomicFieldUpdater_incrementAndGet:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁴ B/op
+ *
+ * AtomicsBenchmark.atomic_construction thrpt 6 1872153219.594 ± 83252749.463 ops/s
+ * AtomicsBenchmark.atomic_construction:gc.alloc.rate.norm thrpt 6 32.000 ± 0.001 B/op
+ *
+ * AtomicsBenchmark.atomic_incrementAndGet thrpt 6 120835704.294 ± 23025991.947 ops/s
+ * AtomicsBenchmark.atomic_incrementAndGet:gc.alloc.rate.norm thrpt 6 ≈ 10⁻⁴ B/op
+ *
+ * AtomicsBenchmark.atomic_read thrpt 6 1968266961.596 ± 57765039.412 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