Skip to content

Commit 779de80

Browse files
dougqhclaude
andcommitted
Make ThreadSafeMapBenchmark lookup index per-thread (remove shared-counter contention)
nextLookupKey used a shared static counter incremented from all @threads(8) — a cache-line-contended race that floors the fastest reads and masks the very differences the benchmark compares (mirrors the per-thread index SingleThreadedMapBenchmark already uses, and the set-benchmark fix in #11721). Maps stay static/shared; only the lookup index goes per-thread via @State(Scope.Thread). Existing Javadoc numbers predate this and need a rerun. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f92aab4 commit 779de80

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

internal-api/src/jmh/java/datadog/trace/util/ThreadSafeMapBenchmark.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import org.openjdk.jmh.annotations.Benchmark;
1010
import org.openjdk.jmh.annotations.Fork;
1111
import org.openjdk.jmh.annotations.Measurement;
12+
import org.openjdk.jmh.annotations.Scope;
13+
import org.openjdk.jmh.annotations.State;
1214
import org.openjdk.jmh.annotations.Threads;
1315
import org.openjdk.jmh.annotations.Warmup;
1416

@@ -67,6 +69,7 @@
6769
@Warmup(iterations = 2)
6870
@Measurement(iterations = 3)
6971
@Threads(8)
72+
@State(Scope.Thread)
7073
public class ThreadSafeMapBenchmark {
7174
static final String[] INSERTION_KEYS = {
7275
"foo", "bar", "baz", "quux", "foobar", "foobaz", "key0", "key1", "key2", "key3"
@@ -86,16 +89,20 @@ static <T> T init(Supplier<T> supplier) {
8689
return supplier.get();
8790
}
8891

89-
static int sharedLookupIndex = 0;
92+
// Per-thread (@State(Scope.Thread)) so cycling the lookup key doesn't contend a shared counter.
93+
// The maps below stay static/shared (the point — concurrent reads of one map); only the index is
94+
// per-thread. A shared counter's cache-line ping-pong would otherwise floor the fastest reads
95+
// (e.g. FlatHashtable's lock-free probe), hiding exactly the differences this benchmark compares.
96+
int lookupIndex = 0;
9097

91-
static String nextLookupKey() {
98+
String nextLookupKey() {
9299
return nextLookupKey(EQUAL_KEYS);
93100
}
94101

95-
static String nextLookupKey(String[] keys) {
96-
int localIndex = ++sharedLookupIndex;
102+
String nextLookupKey(String[] keys) {
103+
int localIndex = ++lookupIndex;
97104
if (localIndex >= keys.length) {
98-
sharedLookupIndex = localIndex = 0;
105+
lookupIndex = localIndex = 0;
99106
}
100107
return keys[localIndex];
101108
}

0 commit comments

Comments
 (0)