Repository navigation
Conversation
…isions Every root probability decision built an OtelTraceState inside the sampling lock, though only W3C injection and OTLP export read it. Install a ProbabilitySamplingState that keeps the trace id bits and rate, and builds the ot member on first read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
🟢 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. |
…hape cost SamplingDecisionBenchmark gains arms that follow a probability decision with the Datadog header, the W3C tracestate header and the OTLP tracestate, so the deferred OtelTraceState is measured where it's built or skipped. ServiceShapePropagationBenchmark measures head, leaf and intermediate services with a default-configured tracer. It only uses API unchanged since v1.66.0, so it can be built onto release tags to put a cost on #12397. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Describe it as a scenario benchmark: each arm is a whole request driven through the tracer's public API, rather than one method in isolation. 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 static review found no actionable regressions in sampling overrides, concurrent publication, propagation, or header caching from deferring OpenTelemetry state construction.
🤖 Bits Code Review · Commit 1d4880b
|
|
||
| SamplingState state = ptags.samplingState(); | ||
|
|
||
| assertSame(state.getOtelTraceState(), state.getOtelTraceState()); |
There was a problem hiding this comment.
could consider adding a multi-threaded test, since this just checks serial access?
What Does This Do
#12397 made every root probability decision build an
OtelTraceState, inside the sampling lock. Only W3Ctracestateinjection and OTLP export ever read it.This PR defers building it for the common case: a fresh probability decision with no inherited
ottracestate member, not rejected by the rate limiter.tryUpdateProbabilitySamplingDecisioninstalls a newProbabilitySamplingState. It keeps only the trace id low-order bits and the rate, and builds theotmember on the firstgetOtelTraceState().OtelTraceStatekeeping its fields final. The CAS runs once per injected or exported trace, uncontended.PropagationTags.SamplingStateis no longerfinal.preservesInheritedOtelPositionnow reads through the getter.installSamplingStateintonextDecisionMakerTagValue, so the new path can share it.Every other path is unchanged:
otmemberforceKeepMotivation
This is part of the follow-ups to #12397's per-trace sampling overhead (APMLP-2048).
Stacked on #12981. Without #12981, moving the decision-maker computation into its own method made the remaining
"-" + mechanismconcat escape. That added 24 B/op to priority-only decisions. With #12981 the concat is gone and that path is unchanged.Benchmark
Decision and header paths:
SamplingDecisionBenchmarkBefore = #12981; after = this branch.
-prof gc, B/op.ptagsProbabilityKeep(decision only)ptagsProbabilityKeepDatadogHeaderptagsProbabilityKeepW3CHeaderptagsProbabilityKeepOtlpTracestateptagsPriorityKeepspanDefaultSamplerKeepspanRuleSamplerKeepspanManualKeepOtelTraceStateis still built, plus 16 B for the two inputsProbabilitySamplingStatecarries.-XX:-DoEscapeAnalysisthe gap is +16 B (1080 → 1096) at equal throughput. The rest is a scalar-replacement win the old code got in this direct-call arm and this code doesn't. It only applies to OTLP export with rule sampling: under OTLP export the default sampler isParentBasedAlwaysOnSampler, a priority-only decision that never creates aProbabilitySamplingState. Real export goes throughOtlpTraceJson.writeSpan, so whether the JIT effect carries over there isn't measured.Scenarios:
PropagationScenariosBenchmarkA scenario benchmark: each arm is a whole request driven through the tracer's public API, with a default-configured tracer (
datadog,tracecontext,baggage):headNoPropagation,headPropagation: a root that decides, with or without an outbound injectleaf,intermediate: extract an upstream decision, with or without relaying itIt's here to put this PR in context of #12397's overall cost. It only uses API unchanged since v1.66.0, so it builds onto both commits.
#12397 alone (
79a1710fcd^vs79a1710fcd, B/op):This PR on that benchmark (default sampler, v1.66.0 → master → this branch):
-f 3: Δ from −104 to +39 B, within ±50–150 B error. The expected +16 B is below resolution.otmember), which this PR doesn't touch. That's tracked separately in APMLP-2049.B/op on the larger scenario arms varies by ±100 B between forks, so treat small deltas there as noise.
Additional Notes
ProbabilitySamplingStateTestcovers:forceKeepstarts from the deferred statedd-trace-coretest suite passes, apart from:TracerConnectionReliabilityTestcases (no Docker locally)DDAgentWriterCombinedTestandPendingTraceBufferTest, which failed under full-suite load and pass when run on their own🤖 Generated with Claude Code