Skip to content

fix: prevent duplicate trace_id after CallTraceHashTable expansion#659

Draft
jbachorik wants to merge 2 commits into
mainfrom
sphinx/fix-jira-PROF-15396
Draft

fix: prevent duplicate trace_id after CallTraceHashTable expansion#659
jbachorik wants to merge 2 commits into
mainfrom
sphinx/fix-jira-PROF-15396

Conversation

@jbachorik

@jbachorik jbachorik commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?:
CallTraceHashTable::put() could assign the same trace_id to two different call traces once the table expanded: capacity doubles on expansion but the new LongHashTable generation's slot numbering restarted from 0, while instance_id (the upper 32 bits of trace_id) stays fixed until the whole table retires. This PR threads a slot_base through each LongHashTable generation so the low 32 bits of trace_id (slot_base + slot) stay unique across all generations of one active tenure, and adds an overflow guard (with a CALLTRACE_STORAGE_EXPANSION_SKIPPED counter) that skips expansion rather than let slot_base + capacity carry into instance_id's bits.

Motivation:
An ASan stress test showed ~4% duplicate trace IDs after expansion, causing downstream JFR constant-pool/symbolication consumers to merge or misattribute samples for the colliding traces.

Additional Notes:
The expansion-overflow guard's boundary check and capacity-doubling logic are extracted into two pure, allocation-free static methods (CallTraceHashTable::wouldExceedSlotIdRange, nextGenerationCapacity) so they can be unit tested directly — reaching the 2^32 boundary via real put() calls would require billions of inserts.

How to test the change?:
New/updated gtest cases in test_callTraceStorage.cpp:

  • ExpansionProducesNoDuplicateTraceIds
  • TraceIdStableAcrossExpansion
  • TwoExpansionsWithinOneTenureNoDuplicateTraceIds
  • CallTraceHashTableOverflowGuardTest.RejectsOnlyValuesThatExceedSlotIdRange
  • CallTraceHashTableOverflowGuardTest.NextGenerationCapacityIsDouble

Run via :ddprof-lib:gtestDebug_test_callTraceStorage; all 18 cases pass.

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles
    credentials of any kind, I've requested a security review (run the dd:platform-security-review
    skill, or file a request via the PSEC review form).
    bewaire also runs automatically on every PR.
  • This PR doesn't touch any of that.
  • JIRA: PROF-15396

Unsure? Have a question? Request a review!

…ROF-15396)

Thread slot_base through LongHashTable generations so trace_id low bits stay
unique across expansions instead of restarting from 0; guard against the
slot range overflowing 2^32 with a counter for observability.
@jbachorik jbachorik added the AI label Jul 14, 2026
@dd-octo-sts

dd-octo-sts Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #29330594689 | Commit: 394018a | Duration: 17m 24s (longest job)

All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - - -
8-ibm - - -
8-j9 - -
8-librca - -
8-orcl - - -
11 - - -
11-j9 - -
11-librca - -
17 - -
17-graal - -
17-j9 - -
17-librca - -
21 - -
21-graal - -
21-librca - -
25 - -
25-graal - -
25-librca - -

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 32 | Failed: 0


Updated: 2026-07-14 12:16:16 UTC

@dd-octo-sts

dd-octo-sts Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (commit a6ab878)

Pipeline: https://gitlab.ddbuild.io/DataDog/apm-reliability/benchmarking-platform/-/pipelines/124506625 Commit: a6ab87878db9d09981bf1530e4df4c4f0c267fe0

⚠️ Significant outliers

  • 🟢 fj-kmeans (JDK 21): runtime -2.9% (2847→2764 ms)
  • 🔴 future-genetic (JDK 25): runtime +3.6% (2028→2101 ms)
Runtime details (per benchmark × JDK)
Benchmark JDK Latest Dev Δ (dev vs latest) Issues L/D
akka-uct 21 ✅ 10287 ms (21 iters) ✅ 10265 ms (21 iters) ≈ -0.2% (±11.4%) — / —
akka-uct 25 ✅ 8865 ms (24 iters) ✅ 8823 ms (24 iters) ≈ -0.5% (±9.4%) — / —
finagle-chirper 21 ✅ 5948 ms (33 iters) ✅ 6028 ms (33 iters) ≈ +1.3% (±25.7%) ⚠️ W:4 / ⚠️ W:3
finagle-chirper 25 ✅ 5455 ms (36 iters) ✅ 5496 ms (36 iters) ≈ +0.8% (±24.1%) ⚠️ W:4 / ⚠️ W:3
fj-kmeans 21 ✅ 2847 ms (66 iters) ✅ 2764 ms (68 iters) 🟢 -2.9% — / —
fj-kmeans 25 ✅ 2811 ms (66 iters) ✅ 2804 ms (66 iters) ≈ -0.2% (±2.6%) — / —
future-genetic 21 ✅ 2063 ms (90 iters) ✅ 2083 ms (89 iters) ≈ +1% (±2.7%) — / —
future-genetic 25 ✅ 2028 ms (91 iters) ✅ 2101 ms (88 iters) 🔴 +3.6% — / —
naive-bayes 21 ✅ 1273 ms (134 iters) ✅ 1273 ms (135 iters) ≈ 0% (±33%) — / —
naive-bayes 25 ✅ 1013 ms (169 iters) ✅ 1013 ms (170 iters) ≈ 0% (±31.4%) — / —
reactors 21 ✅ 15847 ms (15 iters) ✅ 16518 ms (15 iters) ≈ +4.2% (±7.9%) — / —
reactors 25 ✅ 18435 ms (15 iters) ✅ 18690 ms (15 iters) ≈ +1.4% (±4.3%) — / —
Internal counter details (ddprof)

ddprof internal counters, latest / dev (✅ = 0, · = unavailable):

Benchmark JDK Dropped rec Dropped jvmti Dropped trace Skipped WC AGCT fail Unwind fail
akka-uct 21 ✅ / ✅ ✅ / ✅ 2 / ✅ 1947 / 1968 ✅ / ✅ ✅ / ✅
akka-uct 25 ✅ / ✅ ✅ / ✅ ✅ / ✅ 2288 / 2290 ✅ / ✅ ✅ / ✅
finagle-chirper 21 ✅ / ✅ ✅ / ✅ 1 / 3 8620 / 8482 ✅ / ✅ ✅ / ✅
finagle-chirper 25 ✅ / ✅ ✅ / ✅ 1 / 1 8154 / 8569 ✅ / ✅ ✅ / ✅
fj-kmeans 21 ✅ / ✅ ✅ / ✅ ✅ / 3 1268 / 1261 ✅ / ✅ ✅ / ✅
fj-kmeans 25 ✅ / ✅ ✅ / ✅ 1 / 2 1302 / 1258 ✅ / ✅ ✅ / ✅
future-genetic 21 ✅ / ✅ ✅ / ✅ 3 / 1 2907 / 2901 ✅ / ✅ ✅ / ✅
future-genetic 25 ✅ / ✅ ✅ / ✅ 1 / 2 2961 / 2852 ✅ / ✅ ✅ / ✅
naive-bayes 21 ✅ / ✅ ✅ / ✅ 3 / 5 3511 / 3546 ✅ / ✅ ✅ / ✅
naive-bayes 25 ✅ / ✅ ✅ / ✅ 1 / 7 3475 / 3486 ✅ / ✅ ✅ / ✅
reactors 21 ✅ / ✅ ✅ / ✅ 1 / ✅ 1641 / 1558 ✅ / ✅ ✅ / ✅
reactors 25 ✅ / ✅ ✅ / ✅ ✅ / 1 1886 / 1870 ✅ / ✅ ✅ / ✅

@dd-octo-sts

dd-octo-sts Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (commit 9747d1a)

Pipeline: https://gitlab.ddbuild.io/DataDog/apm-reliability/benchmarking-platform/-/pipelines/124510382 Commit: 9747d1ac9df614b76e08905a8081ade783ac6d48

✅ Within expected boundaries

No significant runtime deltas (all within run-to-run noise) and no internal-counter outliers.

Runtime details (per benchmark × JDK)
Benchmark JDK Latest Dev Δ (dev vs latest) Issues L/D
akka-uct 21 ✅ 10295 ms (21 iters) ✅ 10393 ms (21 iters) ≈ +1% (±11.7%) — / —
akka-uct 25 ✅ 8929 ms (24 iters) ✅ 8879 ms (24 iters) ≈ -0.6% (±9.9%) — / —
finagle-chirper 21 ✅ 5918 ms (33 iters) ✅ 5995 ms (33 iters) ≈ +1.3% (±25.7%) ⚠️ W:4 / ⚠️ W:3
finagle-chirper 25 ✅ 5466 ms (36 iters) ✅ 5523 ms (36 iters) ≈ +1% (±24.6%) ⚠️ W:3 / ⚠️ W:3
fj-kmeans 21 ✅ 2725 ms (68 iters) ✅ 2722 ms (68 iters) ≈ -0.1% (±2.7%) — / —
fj-kmeans 25 ✅ 2813 ms (66 iters) ✅ 2818 ms (66 iters) ≈ +0.2% (±2.6%) — / —
future-genetic 21 ✅ 2054 ms (90 iters) ✅ 2102 ms (88 iters) ≈ +2.3% (±2.7%) — / —
future-genetic 25 ✅ 2087 ms (89 iters) ✅ 2056 ms (91 iters) ≈ -1.5% (±2.6%) — / —
naive-bayes 21 ✅ 1237 ms (138 iters) ✅ 1245 ms (137 iters) ≈ +0.6% (±33%) — / —
naive-bayes 25 ✅ 1009 ms (169 iters) ✅ 1021 ms (167 iters) ≈ +1.2% (±31.7%) — / —
reactors 21 ✅ 16431 ms (15 iters) ✅ 16392 ms (15 iters) ≈ -0.2% (±7.2%) — / —
reactors 25 ✅ 18177 ms (15 iters) ✅ 18521 ms (15 iters) ≈ +1.9% (±3.8%) — / —
Internal counter details (ddprof)

ddprof internal counters, latest / dev (✅ = 0, · = unavailable):

Benchmark JDK Dropped rec Dropped jvmti Dropped trace Skipped WC AGCT fail Unwind fail
akka-uct 21 ✅ / ✅ ✅ / ✅ 4 / 1 2020 / 1951 ✅ / ✅ ✅ / ✅
akka-uct 25 ✅ / ✅ ✅ / ✅ 3 / 1 2243 / 2310 ✅ / ✅ ✅ / ✅
finagle-chirper 21 ✅ / ✅ ✅ / ✅ 4 / 3 8170 / 8615 ✅ / ✅ ✅ / ✅
finagle-chirper 25 ✅ / ✅ ✅ / ✅ 1 / 1 8215 / 8832 ✅ / ✅ ✅ / ✅
fj-kmeans 21 ✅ / ✅ ✅ / ✅ 1 / 4 1271 / 1271 ✅ / ✅ ✅ / ✅
fj-kmeans 25 ✅ / ✅ ✅ / ✅ 3 / 2 1278 / 1303 ✅ / ✅ ✅ / ✅
future-genetic 21 ✅ / ✅ ✅ / ✅ 3 / ✅ 2904 / 2968 ✅ / ✅ ✅ / ✅
future-genetic 25 ✅ / ✅ ✅ / ✅ 1 / ✅ 2924 / 2882 ✅ / ✅ ✅ / ✅
naive-bayes 21 ✅ / ✅ ✅ / ✅ 2 / 5 3484 / 3496 ✅ / ✅ ✅ / ✅
naive-bayes 25 ✅ / ✅ ✅ / ✅ 4 / 6 3457 / 3490 ✅ / ✅ ✅ / ✅
reactors 21 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1540 / 1604 ✅ / ✅ ✅ / ✅
reactors 25 ✅ / ✅ ✅ / ✅ ✅ / ✅ 1866 / 1850 ✅ / ✅ ✅ / ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant