From a4fae48c28a26a60797689bf0b478258e88e7c2c Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Tue, 17 Feb 2026 17:28:31 -0800 Subject: [PATCH 1/2] [web-shared] reduce redundant render --- .../components/trace-viewer/trace-viewer.tsx | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/web-shared/src/components/trace-viewer/trace-viewer.tsx b/packages/web-shared/src/components/trace-viewer/trace-viewer.tsx index 341c00a5ad..091c875a98 100644 --- a/packages/web-shared/src/components/trace-viewer/trace-viewer.tsx +++ b/packages/web-shared/src/components/trace-viewer/trace-viewer.tsx @@ -116,6 +116,7 @@ export function TraceViewerTimeline({ null ); const prevSpanMapRef = useRef['map']>({}); + const prevSizeRef = useRef<{ width: number; height: number } | null>(null); useEffect(() => { const { root: newRoot, map: newSpanMap } = parseTrace(trace); @@ -149,19 +150,36 @@ export function TraceViewerTimeline({ // references) does NOT restart. const oldRoot = prevRootRef.current; const oldSpanMap = prevSpanMapRef.current; + let didChange = false; - oldRoot.endTime = newRoot.endTime; - oldRoot.duration = newRoot.duration; + if ( + oldRoot.endTime !== newRoot.endTime || + oldRoot.duration !== newRoot.duration + ) { + oldRoot.endTime = newRoot.endTime; + oldRoot.duration = newRoot.duration; + didChange = true; + } for (const [id, newNode] of Object.entries(newSpanMap)) { const oldNode = oldSpanMap[id]; if (oldNode) { - oldNode.endTime = newNode.endTime; - oldNode.duration = newNode.duration; + if ( + oldNode.endTime !== newNode.endTime || + oldNode.duration !== newNode.duration + ) { + oldNode.endTime = newNode.endTime; + oldNode.duration = newNode.duration; + didChange = true; + } Object.assign(oldNode.span, newNode.span); } } + if (!didChange) { + return; + } + // Trigger re-render (scale/markers) without restarting the worker. // useLiveTick handles continuous scale recalculation for live runs. dispatch({ type: 'forceRender' }); @@ -193,11 +211,23 @@ export function TraceViewerTimeline({ const onResize = (): void => { const padding = 2 * TIMELINE_PADDING; const rect = $el.getBoundingClientRect(); + const nextWidth = rect.width - padding; + const nextHeight = rect.height; + const prevSize = prevSizeRef.current; + + if ( + prevSize && + prevSize.width === nextWidth && + prevSize.height === nextHeight + ) { + return; + } + prevSizeRef.current = { width: nextWidth, height: nextHeight }; dispatch({ type: 'setSize', - width: rect.width - padding, - height: rect.height, + width: nextWidth, + height: nextHeight, }); }; From ada9de79f7556ca7e0e90ee2573f23c83d07eb21 Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Tue, 17 Feb 2026 17:33:39 -0800 Subject: [PATCH 2/2] [web-shared] add changeset --- .changeset/loose-clocks-tease.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/loose-clocks-tease.md diff --git a/.changeset/loose-clocks-tease.md b/.changeset/loose-clocks-tease.md new file mode 100644 index 0000000000..b5824908c0 --- /dev/null +++ b/.changeset/loose-clocks-tease.md @@ -0,0 +1,5 @@ +--- +"@workflow/web-shared": patch +--- + +Minor perf hardening for trace viewer