Skip to content

Commit 4205397

Browse files
dougqhdevflow.devflow-routing-intake
andauthored
Cache hashCode on UTF8BytesString (#11444)
Cache hashCode on UTF8BytesString UTF8BytesString.hashCode() currently delegates straight through to String.hashCode() on every call. String already caches its own hash, but the trip out of UTF8BytesString and through String's hash-field check still costs a virtual dispatch + field read + branch on every invocation. Caches the hash on UTF8BytesString itself once computed. Benign-race pattern, identical to the existing utf8Bytes lazy initializer: two threads computing the same value produce identical results, and int writes are atomic per JLS so a reader can't observe a partial value. Measured on the metrics subsystem's adversarial JMH bench (8 producer threads, high-cardinality unique-per-op labels), this lifts aggregate throughput from 5.17M to 5.78M ops/s -- ~12% improvement, with the per-iteration distribution shifting systematically upward across all five measurement iterations. The win is bigger in production-like workloads with repeated keys, since the cardinality-handler intern pool means the same UTF8BytesString instance gets hashed repeatedly in subsequent reporting cycles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Merge branch 'master' into dougqh/utf8bytesstring-cache-hashcode Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
1 parent 970f5ee commit 4205397

1 file changed

Lines changed: 13 additions & 1 deletion

File tree

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/UTF8BytesString.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ public static UTF8BytesString create(ByteBuffer utf8BytesBuffer) {
5858

5959
private final String string;
6060
private byte[] utf8Bytes;
61+
// Lazy hashCode cache. {@link String} already caches its own {@code hashCode} internally, but
62+
// the inter-class call through {@code string.hashCode()} still costs a virtual dispatch + the
63+
// String's own cached-hash field read + branch -- caching here saves all of that on subsequent
64+
// calls. Benign race in the same shape as {@link #utf8Bytes}: two threads computing the same
65+
// hash in parallel both produce the same value, and {@code int} writes are atomic per JLS so a
66+
// reader cannot observe a partial value.
67+
private int cachedHashCode;
6168

6269
private UTF8BytesString(String string) {
6370
this.string = string;
@@ -114,7 +121,12 @@ public boolean equals(Object o) {
114121

115122
@Override
116123
public int hashCode() {
117-
return this.string.hashCode();
124+
int h = this.cachedHashCode;
125+
if (h == 0) {
126+
h = this.string.hashCode();
127+
this.cachedHashCode = h;
128+
}
129+
return h;
118130
}
119131

120132
@Override

0 commit comments

Comments
 (0)