Skip to content

Commit 1d68cf4

Browse files
authored
Improve get trace name performance (#574)
* Memoize getTraceName to improve render time by 3x Signed-off-by: Everett Ross <reverett@uber.com> * Clean up memoization approach Signed-off-by: Everett Ross <reverett@uber.com> * Fix merge Signed-off-by: Everett Ross <reverett@uber.com> * Fix getTraceNameImpl to be O n Signed-off-by: Everett Ross <reverett@uber.com>
1 parent 8e348fd commit 1d68cf4

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

packages/jaeger-ui/src/model/trace-viewer.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,35 @@ import _memoize from 'lodash/memoize';
1616

1717
import { Span } from '../types/trace';
1818

19-
type spansDict = { [index: string]: Span };
20-
2119
export function _getTraceNameImpl(spans: Span[]) {
22-
const allTraceSpans: spansDict = spans.reduce((dict, span) => ({ ...dict, [span.spanID]: span }), {});
23-
const rootSpan = spans
24-
.filter(sp => {
25-
if (!sp.references || !sp.references.length) {
26-
return true;
27-
}
28-
const parentIDs = sp.references.filter(r => r.traceID === sp.traceID).map(r => r.spanID);
29-
30-
// returns true if no parent from this trace found
31-
return !parentIDs.some(pID => Boolean(allTraceSpans[pID]));
32-
})
33-
.sort((sp1, sp2) => {
34-
const sp1ParentsNum = sp1.references ? sp1.references.length : 0;
35-
const sp2ParentsNum = sp2.references ? sp2.references.length : 0;
36-
37-
return sp1ParentsNum - sp2ParentsNum || sp1.startTime - sp2.startTime;
38-
})[0];
39-
40-
return rootSpan ? `${rootSpan.process.serviceName}: ${rootSpan.operationName}` : '';
20+
// Use a span with no references to another span in given array
21+
// prefering the span with the fewest references
22+
// using start time as a tie breaker
23+
let candidateSpan: Span | undefined;
24+
const allIDs: Set<string> = new Set(spans.map(({ spanID }) => spanID));
25+
26+
for (let i = 0; i < spans.length; i++) {
27+
const hasInternalRef =
28+
spans[i].references &&
29+
spans[i].references.some(({ traceID, spanID }) => traceID === spans[i].traceID && allIDs.has(spanID));
30+
if (hasInternalRef) continue;
31+
32+
if (!candidateSpan) {
33+
candidateSpan = spans[i];
34+
continue;
35+
}
36+
37+
const thisRefLength = (spans[i].references && spans[i].references.length) || 0;
38+
const candidateRefLength = (candidateSpan.references && candidateSpan.references.length) || 0;
39+
40+
if (
41+
thisRefLength < candidateRefLength ||
42+
(thisRefLength === candidateRefLength && spans[i].startTime < candidateSpan.startTime)
43+
) {
44+
candidateSpan = spans[i];
45+
}
46+
}
47+
return candidateSpan ? `${candidateSpan.process.serviceName}: ${candidateSpan.operationName}` : '';
4148
}
4249

4350
export const getTraceName = _memoize(_getTraceNameImpl, (spans: Span[]) => {

0 commit comments

Comments
 (0)