Skip to content

Commit bba3921

Browse files
committed
spotless
1 parent 73b19dd commit bba3921

5 files changed

Lines changed: 422 additions & 419 deletions

File tree

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

Lines changed: 105 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import java.util.TreeMap;
55
import java.util.concurrent.ThreadLocalRandom;
66
import java.util.function.Supplier;
7-
87
import org.openjdk.jmh.annotations.Benchmark;
98
import org.openjdk.jmh.annotations.Fork;
109
import org.openjdk.jmh.annotations.Measurement;
@@ -13,171 +12,171 @@
1312
import org.openjdk.jmh.infra.Blackhole;
1413

1514
/**
16-
* <ul>Benchmark to illustrate the trade-offs around case-insensitive Map look-ups - using either...
17-
* <li>(RECOMMENDED) TreeMap with Comparator of String::compareToIgnoreCase
18-
* <li>HashMap with look-ups using String::to<X>Case
15+
*
16+
*
17+
* <ul>
18+
* Benchmark to illustrate the trade-offs around case-insensitive Map look-ups - using either...
19+
* <li>(RECOMMENDED) TreeMap with Comparator of String::compareToIgnoreCase
20+
* <li>HashMap with look-ups using String::to<X>Case
1921
* </ul>
20-
*
21-
* <p>For case-insensitive lookups, TreeMap map creation is consistently faster because it
22-
* avoids String::to<X>Case calls.
23-
*
24-
* <p>Despite calls to String::to<X>Case, HashMap lookups are faster in single threaded
22+
*
23+
* <p>For case-insensitive lookups, TreeMap map creation is consistently faster because it avoids
24+
* String::to<X>Case calls.
25+
*
26+
* <p>Despite calls to String::to<X>Case, HashMap lookups are faster in single threaded
2527
* microbenchmark by 50% but are worse when frequently called in a multi-threaded system.
26-
*
28+
*
2729
* <p>With many threads, the extra allocation from calling String::to<X>Case leads to frequent GCs
28-
* which has adverse impacts on the whole system.
29-
*
30-
* <code>
30+
* which has adverse impacts on the whole system. <code>
3131
* MacBook M1 with 1 thread (Java 21)
32-
*
32+
*
3333
* Benchmark Mode Cnt Score Error Units
3434
* CaseInsensitiveMapBenchmark.create_hashMap thrpt 6 994213.041 ± 15718.903 ops/s
3535
* CaseInsensitiveMapBenchmark.create_treeMap thrpt 6 1522900.015 ± 21646.688 ops/s
36-
*
36+
*
3737
* CaseInsensitiveMapBenchmark.get_hashMap thrpt 6 69149862.293 ± 9168648.566 ops/s
3838
* CaseInsensitiveMapBenchmark.get_treeMap thrpt 6 42796699.230 ± 9029447.805 ops/s
39-
* </code>
40-
*
41-
* <code>
39+
* </code> <code>
4240
* MacBook M1 with 8 threads (Java 21)
43-
*
41+
*
4442
* Benchmark Mode Cnt Score Error Units
4543
* CaseInsensitiveMapBenchmark.create_hashMap thrpt 6 6641003.483 ± 543210.409 ops/s
4644
* CaseInsensitiveMapBenchmark.create_treeMap thrpt 6 10030191.764 ± 1308865.113 ops/s
47-
*
45+
*
4846
* CaseInsensitiveMapBenchmark.get_hashMap thrpt 6 38748031.837 ± 9012072.804 ops/s
4947
* CaseInsensitiveMapBenchmark.get_treeMap thrpt 6 173495470.789 ± 27824904.999 ops/s
5048
* </code>
5149
*/
5250
@Fork(2)
53-
@Warmup(iterations=2)
54-
@Measurement(iterations=3)
51+
@Warmup(iterations = 2)
52+
@Measurement(iterations = 3)
5553
@Threads(8)
5654
public class CaseInsensitiveMapBenchmark {
57-
static final String[] PREFIXES = {
58-
"foo",
59-
"bar",
60-
"baz",
61-
"quux"
62-
};
63-
55+
static final String[] PREFIXES = {"foo", "bar", "baz", "quux"};
56+
6457
static final int NUM_SUFFIXES = 4;
65-
58+
6659
static <T> T init(Supplier<T> supplier) {
67-
return supplier.get();
60+
return supplier.get();
6861
}
6962

70-
static final String[] UPPER_PREFIXES = init(() -> {
71-
String[] upperPrefixes = new String[PREFIXES.length];
72-
for ( int i = 0; i < PREFIXES.length; ++i ) {
73-
upperPrefixes[i] = PREFIXES[i].toUpperCase();
74-
}
75-
return upperPrefixes;
76-
});
77-
78-
static final String[] LOOKUP_KEYS = init(() -> {
79-
ThreadLocalRandom curRandom = ThreadLocalRandom.current();
80-
81-
String[] keys = new String[32];
82-
for ( int i = 0; i < keys.length; ++i ) {
83-
int prefixIndex = curRandom.nextInt(PREFIXES.length);
84-
boolean toUpper = curRandom.nextBoolean();
85-
int suffixIndex = curRandom.nextInt(NUM_SUFFIXES + 1);
86-
87-
String key = PREFIXES[prefixIndex] + "-" + suffixIndex;
88-
keys[i] = toUpper ? key.toUpperCase() : key.toLowerCase();
89-
}
90-
return keys;
91-
});
92-
63+
static final String[] UPPER_PREFIXES =
64+
init(
65+
() -> {
66+
String[] upperPrefixes = new String[PREFIXES.length];
67+
for (int i = 0; i < PREFIXES.length; ++i) {
68+
upperPrefixes[i] = PREFIXES[i].toUpperCase();
69+
}
70+
return upperPrefixes;
71+
});
72+
73+
static final String[] LOOKUP_KEYS =
74+
init(
75+
() -> {
76+
ThreadLocalRandom curRandom = ThreadLocalRandom.current();
77+
78+
String[] keys = new String[32];
79+
for (int i = 0; i < keys.length; ++i) {
80+
int prefixIndex = curRandom.nextInt(PREFIXES.length);
81+
boolean toUpper = curRandom.nextBoolean();
82+
int suffixIndex = curRandom.nextInt(NUM_SUFFIXES + 1);
83+
84+
String key = PREFIXES[prefixIndex] + "-" + suffixIndex;
85+
keys[i] = toUpper ? key.toUpperCase() : key.toLowerCase();
86+
}
87+
return keys;
88+
});
89+
9390
static int sharedLookupIndex = 0;
94-
91+
9592
static String nextLookupKey() {
96-
int localIndex = ++sharedLookupIndex;
97-
if ( localIndex >= LOOKUP_KEYS.length ) {
98-
sharedLookupIndex = localIndex = 0;
99-
}
100-
return LOOKUP_KEYS[localIndex];
93+
int localIndex = ++sharedLookupIndex;
94+
if (localIndex >= LOOKUP_KEYS.length) {
95+
sharedLookupIndex = localIndex = 0;
96+
}
97+
return LOOKUP_KEYS[localIndex];
10198
}
102-
99+
103100
@Benchmark
104101
public void create_baseline(Blackhole blackhole) {
105-
for ( int suffix = 0; suffix < NUM_SUFFIXES; ++suffix ) {
106-
for ( String prefix: PREFIXES ) {
107-
blackhole.consume(prefix + "-" + suffix);
108-
blackhole.consume(Integer.valueOf(suffix));
102+
for (int suffix = 0; suffix < NUM_SUFFIXES; ++suffix) {
103+
for (String prefix : PREFIXES) {
104+
blackhole.consume(prefix + "-" + suffix);
105+
blackhole.consume(Integer.valueOf(suffix));
109106
}
110-
}
111-
for ( int suffix = 0; suffix < NUM_SUFFIXES; suffix +=2 ) {
112-
for ( String prefix: UPPER_PREFIXES ) {
113-
blackhole.consume(prefix + "-" + suffix);
114-
blackhole.consume(Integer.valueOf(suffix + 1));
107+
}
108+
for (int suffix = 0; suffix < NUM_SUFFIXES; suffix += 2) {
109+
for (String prefix : UPPER_PREFIXES) {
110+
blackhole.consume(prefix + "-" + suffix);
111+
blackhole.consume(Integer.valueOf(suffix + 1));
115112
}
116-
}
113+
}
117114
}
118-
115+
119116
@Benchmark
120117
public void lookup_baseline(Blackhole blackhole) {
121-
blackhole.consume(nextLookupKey());
118+
blackhole.consume(nextLookupKey());
122119
}
123-
120+
124121
@Benchmark
125122
public HashMap<String, Integer> create_hashMap() {
126123
return _create_hashMap();
127124
}
128-
125+
129126
static HashMap<String, Integer> _create_hashMap() {
130-
HashMap<String, Integer> map = new HashMap<>();
131-
for ( int suffix = 0; suffix < NUM_SUFFIXES; ++suffix ) {
132-
for ( String prefix: PREFIXES ) {
133-
map.put((prefix + "-" + suffix).toLowerCase(), suffix); // arguable, but real caller probably doesn't know the case ahead-of-time
127+
HashMap<String, Integer> map = new HashMap<>();
128+
for (int suffix = 0; suffix < NUM_SUFFIXES; ++suffix) {
129+
for (String prefix : PREFIXES) {
130+
map.put(
131+
(prefix + "-" + suffix).toLowerCase(),
132+
suffix); // arguable, but real caller probably doesn't know the case ahead-of-time
134133
}
135-
}
136-
for ( int suffix = 0; suffix < NUM_SUFFIXES; suffix +=2 ) {
137-
for ( String prefix: UPPER_PREFIXES ) {
138-
map.put((prefix + "-" + suffix).toLowerCase(), suffix + 1);
134+
}
135+
for (int suffix = 0; suffix < NUM_SUFFIXES; suffix += 2) {
136+
for (String prefix : UPPER_PREFIXES) {
137+
map.put((prefix + "-" + suffix).toLowerCase(), suffix + 1);
139138
}
140-
}
139+
}
141140
return map;
142141
}
143-
142+
144143
static final HashMap<String, Integer> HASH_MAP = _create_hashMap();
145144

146145
@Benchmark
147146
public Integer lookup_hashMap() {
148-
// This benchmark is still "correct" in multi-threaded context,
149-
// Map is populated under the class initialization lock and not changed thereafter
150-
return HASH_MAP.get(nextLookupKey().toLowerCase());
147+
// This benchmark is still "correct" in multi-threaded context,
148+
// Map is populated under the class initialization lock and not changed thereafter
149+
return HASH_MAP.get(nextLookupKey().toLowerCase());
151150
}
152-
151+
153152
@Benchmark
154153
public TreeMap<String, Integer> create_treeMap() {
155-
return _create_treeMap();
154+
return _create_treeMap();
156155
}
157-
156+
158157
static TreeMap<String, Integer> _create_treeMap() {
159-
TreeMap<String, Integer> map = new TreeMap<>(String::compareToIgnoreCase);
160-
for ( int suffix = 0; suffix < NUM_SUFFIXES; ++suffix ) {
161-
for ( String prefix: PREFIXES ) {
162-
map.put(prefix + "-" + suffix, suffix);
158+
TreeMap<String, Integer> map = new TreeMap<>(String::compareToIgnoreCase);
159+
for (int suffix = 0; suffix < NUM_SUFFIXES; ++suffix) {
160+
for (String prefix : PREFIXES) {
161+
map.put(prefix + "-" + suffix, suffix);
163162
}
164-
}
165-
for ( int suffix = 0; suffix < NUM_SUFFIXES; suffix +=2 ) {
166-
for ( String prefix: UPPER_PREFIXES ) {
167-
map.put(prefix + "-" + suffix, suffix + 1);
163+
}
164+
for (int suffix = 0; suffix < NUM_SUFFIXES; suffix += 2) {
165+
for (String prefix : UPPER_PREFIXES) {
166+
map.put(prefix + "-" + suffix, suffix + 1);
168167
}
169-
}
168+
}
170169
return map;
171170
}
172-
171+
173172
static final TreeMap<String, Integer> TREE_MAP = _create_treeMap();
174-
173+
175174
@Benchmark
176175
public Integer lookup_treeMap() {
177-
// This benchmark is still "correct" in multi-threaded context,
178-
// Map is populated under the initial class initialization lock and not changed thereafter
179-
return TREE_MAP.get(nextLookupKey());
176+
// This benchmark is still "correct" in multi-threaded context,
177+
// Map is populated under the initial class initialization lock and not changed thereafter
178+
return TREE_MAP.get(nextLookupKey());
180179
}
181-
180+
182181
// TODO: Add ConcurrentSkipListMap & synchronized HashMap & TreeMap
183182
}

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@
99
import org.openjdk.jmh.annotations.Warmup;
1010

1111
/**
12-
* <ul>Benchmark comparing HashingUtils.hash to Objects.hash
13-
* <li>(RECOMMENDED) HashingUtils.hash - avoids var-arg creation
14-
* <li>Object.hash - high allocation overhead from var-ags
12+
*
13+
*
14+
* <ul>
15+
* Benchmark comparing HashingUtils.hash to Objects.hash
16+
* <li>(RECOMMENDED) HashingUtils.hash - avoids var-arg creation
17+
* <li>Object.hash - high allocation overhead from var-ags
1518
* </ul>
16-
*
17-
* <p>In contrast to java.util.Objects.hash, datadog.util.HashingUtils.hash has overrides for different
18-
* parameter counts that allow most callers to avoid calling the var-arg version. This avoids the
19-
* common situation where the JIT's escape analysis is unable to elide the var-arg array allocation.
19+
*
20+
* <p>In contrast to java.util.Objects.hash, datadog.util.HashingUtils.hash has overrides for
21+
* different parameter counts that allow most callers to avoid calling the var-arg version. This
22+
* avoids the common situation where the JIT's escape analysis is unable to elide the var-arg array
23+
* allocation.
2024
*
2125
* <p>This results in 3-4x throughput, but more importantly no allocation as compared to GiBs / sec
2226
* with var-args. <code>

0 commit comments

Comments
 (0)