Repository navigation
Conversation
Every keep decision built "-" + samplingMechanism and then validated, hashed and looked it up in TagValue's cache. The mechanisms are a small fixed set, so build their TagValues once and index by mechanism, falling back to TagValue.from for anything beyond the table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
Measures the per-trace propagation-tag bookkeeping done on a root sampling decision, both in a bare start/sample/finish span and on fresh PropagationTags with no span around it, for the default, rule and manual keep paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
More details
The precomputed decision-maker values preserve existing formatting, the negative-mechanism guard, and fallback behavior for mechanisms outside the table.
🤖 Bits Code Review · Commit 4ddb5d9
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
What Does This Do
PTags.installSamplingStatebuilt the_dd.p.dmvalue withTagValue.from("-" + samplingMechanism)on every keep decision. That allocated aString, then ran validation, hashing and a lookup inTagValue's 128-entry cache. All of this happens insidesamplingStateLock.This PR builds the
TagValues for mechanisms 0–15 once, at class init, and indexes them by mechanism. Larger mechanisms still go throughTagValue.from. The negative/UNKNOWNguard is unchanged.Motivation
This is the first of several small follow-ups on per-trace sampling overhead in propagation tags. The others are the eager
OtelTraceStatefrom #12397 (APMLP-2048), the per-PTagslock object, and a race in the single-entry Knuth sampling-rate cache. Those will come as separate PRs.The concat itself is older than #12397. #12397 moved it inside the sampling lock.
Benchmark
This PR adds
SamplingDecisionBenchmark:span*arms run a bare root span through start → sample → finish.ptags*arms make the decision on freshPropagationTagswith no span around it.Before =
master'sPTagsFactory; after = this branch. Both runs used-f 1 -wi 3 -w 2s -i 5 -r 3s -t 8 -prof gcon JDK 17 / M-series laptop. B/op is the primary signal. Throughput comes from a single fork and is directional only.ptagsPriorityKeepptagsProbabilityKeepspanDefaultSamplerKeepspanRuleSamplerKeepspanManualKeepspanDefaultSamplerKeepB/op varied run to run (±94), so treat its Δ as approximate.spanManualKeepalso varies between runs: a later run of the same post-change jar measured 888 B/op, not 840. Its Δ could be −48 rather than −96. Theptags*arms gave the same values in every run.ptags*arms still allocate 150–220 B per trace, forPTagsitself, its lock object,SamplingStateand the eagerOtelTraceState. Those are the targets of the follow-up PRs.Additional Notes
TagValue's shared 128-entry cache.DecisionMakerTagValueTestcovers values inside and beyond the table, and instance reuse.datadog.trace.core.propagation.*,DDSpanContextPropagationTagsTestandCoreSpanBuilderTestpass locally.🤖 Generated with Claude Code