Skip to content

Commit 5fb65b4

Browse files
Samuronpichlermarc
andauthored
perf(export): do not allocate arrays if resource has no pending async attributes (#4550)
* perf(eport): do not allocate arrays if resource has no pending async attributes * perf(export): do not use splice if fit in one batch * Update CHANGELOG.md Co-authored-by: Marc Pichler <[email protected]> --------- Co-authored-by: Marc Pichler <[email protected]>
1 parent f9a0d3e commit 5fb65b4

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/
1111

1212
### :rocket: (Enhancement)
1313

14+
* perf(sdk-trace-base): do not allocate arrays if resource has no pending async attributes
15+
1416
### :bug: (Bug Fix)
1517

1618
* fix(sdk-metrics): increase the depth of the output to the console such that objects in the metric are printed fully to the console [#4522](https://github.com/open-telemetry/opentelemetry-js/pull/4522) @JacksonWeber

packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,13 @@ export abstract class BatchSpanProcessorBase<T extends BufferConfig>
181181
// Reset the finished spans buffer here because the next invocations of the _flush method
182182
// could pass the same finished spans to the exporter if the buffer is cleared
183183
// outside the execution of this callback.
184-
const spans = this._finishedSpans.splice(0, this._maxExportBatchSize);
184+
let spans: ReadableSpan[];
185+
if (this._finishedSpans.length <= this._maxExportBatchSize) {
186+
spans = this._finishedSpans;
187+
this._finishedSpans = [];
188+
} else {
189+
spans = this._finishedSpans.splice(0, this._maxExportBatchSize);
190+
}
185191

186192
const doExport = () =>
187193
this._exporter.export(spans, result => {
@@ -195,19 +201,24 @@ export abstract class BatchSpanProcessorBase<T extends BufferConfig>
195201
);
196202
}
197203
});
198-
const pendingResources = spans
199-
.map(span => span.resource)
200-
.filter(resource => resource.asyncAttributesPending);
204+
205+
let pendingResources: Array<Promise<void>> | null = null;
206+
for (let i = 0, len = spans.length; i < len; i++) {
207+
const span = spans[i];
208+
if (
209+
span.resource.asyncAttributesPending &&
210+
span.resource.waitForAsyncAttributes
211+
) {
212+
pendingResources ??= [];
213+
pendingResources.push(span.resource.waitForAsyncAttributes());
214+
}
215+
}
201216

202217
// Avoid scheduling a promise to make the behavior more predictable and easier to test
203-
if (pendingResources.length === 0) {
218+
if (pendingResources === null) {
204219
doExport();
205220
} else {
206-
Promise.all(
207-
pendingResources.map(
208-
resource => resource.waitForAsyncAttributes?.()
209-
)
210-
).then(doExport, err => {
221+
Promise.all(pendingResources).then(doExport, err => {
211222
globalErrorHandler(err);
212223
reject(err);
213224
});

0 commit comments

Comments
 (0)