Skip to content

Commit cbf2cbf

Browse files
BridgeARbengl
authored andcommitted
bench(spans): discard native mutations before processing
## Summary Change-queue flushing consumed 95.8% of the deferred-finish profile and kept the eight-sample CI variant running when the 30-minute job expired. ## Why The benchmark is meant to isolate span construction and finish, but it applied and exported every queued native mutation. Discarding those mutations reduced the same 250,000-span process from 23.11 s to 0.60 s. Native event samples still drain because libdatadog applies events directly. ## Test plan - Run all span variants through three fresh sirun matrices. - Run changed-line coverage and full lint.
1 parent 56f9631 commit cbf2cbf

3 files changed

Lines changed: 26 additions & 14 deletions

File tree

benchmark/sirun/spans/README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
This test initializes a tracer with the no-op scope manager. It then creates
2-
many spans, and depending on the variant, either finishes all of them as they
3-
are created, or later on once they're all created. Prior to creating any spans,
4-
it modifies the processor instance so that no span processing (or exporting) is
5-
done, and it simply stops storing the spans.
1+
This benchmark measures span construction and finish with the no-op scope manager. Ordinary native mutations are
2+
discarded before processing or export; native events are drained because libdatadog applies them directly.

benchmark/sirun/spans/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"DD_TRACE_SCOPE": "noop",
4343
"FINISH": "now",
4444
"SHAPE": "tags-and-otel",
45-
"OPERATIONS": "100000"
45+
"OPERATIONS": "50000"
4646
}
4747
}
4848
}

benchmark/sirun/spans/spans.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,27 @@ const { createNativeSpanDrain } = require('../native-span-drain')
99
nock.disableNetConnect()
1010
nock('http://127.0.0.1:8126').persist().put(/.*/).reply(200, '{}').post(/.*/).reply(200, '{}')
1111

12+
const { FINISH, SHAPE = 'plain' } = process.env
13+
1214
const tracer = require('../../..').init({ hostname: '127.0.0.1', port: 8126 })
13-
const nativeSpanDrain = createNativeSpanDrain(tracer)
15+
const nativeSpans = tracer._tracer._nativeSpans
16+
const nativeSpanDrain = SHAPE === 'tags-and-otel' ? createNativeSpanDrain(tracer) : undefined
17+
18+
let queuedSpans = 0
1419

20+
/** @param {import('../../../packages/dd-trace/src/opentracing/span')} span */
1521
tracer._tracer._processor.process = function process (span) {
1622
const trace = span.context()._trace
17-
nativeSpanDrain.add(span)
23+
if (nativeSpanDrain) {
24+
nativeSpanDrain.add(span)
25+
} else if (nativeSpans && ++queuedSpans === BATCH) {
26+
// This benchmark excludes processing and export; discard queued native mutations before the buffer fills.
27+
nativeSpans.resetChangeQueue()
28+
queuedSpans = 0
29+
}
1830
this._erase(trace, [])
1931
}
2032

21-
const { FINISH, SHAPE = 'plain' } = process.env
22-
2333
// Total spans created per process. The count stays env-driven so CI can keep
2434
// each native-mode variant under the job timeout while still making tracer load
2535
// a small share of the measured run.
@@ -104,14 +114,18 @@ function startOne () {
104114
}
105115

106116
async function main () {
107-
await nativeSpanDrain.drain()
117+
await nativeSpanDrain?.drain()
108118

109119
guard.loopStart()
110-
if (FINISH === 'now') {
120+
if (FINISH === 'now' && nativeSpanDrain) {
111121
for (let iteration = 0; iteration < OPERATIONS; iteration++) {
112122
startOne().finish()
113123
if (nativeSpanDrain.needsDrain()) await nativeSpanDrain.drain()
114124
}
125+
} else if (FINISH === 'now') {
126+
for (let iteration = 0; iteration < OPERATIONS; iteration++) {
127+
startOne().finish()
128+
}
115129
} else {
116130
// Deferred finish in batches: start BATCH spans, finish them after the batch is
117131
// built (so each finishes off the active path), then drop the references.
@@ -126,10 +140,11 @@ async function main () {
126140
}
127141
spans.length = 0
128142
remaining -= size
129-
if (nativeSpanDrain.needsDrain()) await nativeSpanDrain.drain()
143+
if (nativeSpanDrain?.needsDrain()) await nativeSpanDrain.drain()
130144
}
131145
}
132-
await nativeSpanDrain.drain()
146+
await nativeSpanDrain?.drain()
147+
nativeSpans?.resetChangeQueue()
133148
// Native-mode CI counts are intentionally lower than the old JS-only counts so
134149
// the candidate shard finishes before the job timeout. The older baseline source
135150
// can run those counts in under a second, so allow a higher startup share there

0 commit comments

Comments
 (0)