diff --git a/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx b/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx
index a49c568ed1eb..26a1f005ff68 100644
--- a/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx
+++ b/web-console/src/views/workbench-view/execution-stages-pane/execution-stages-pane.tsx
@@ -51,6 +51,7 @@ import {
clamp,
deepGet,
filterMap,
+ formatByteRate,
formatBytesCompact,
formatDurationWithMs,
formatDurationWithMsIfNeeded,
@@ -97,6 +98,23 @@ const formatFileOfTotal = (files: number, totalFiles: number) =>
const formatFileOfTotalForBrace = (files: number, totalFiles: number) =>
`(${formatInteger(files)} /GB ${formatInteger(totalFiles)})`;
+function formatLoadTooltip(
+ loadFiles: number,
+ loadBytes?: number,
+ loadTime?: number,
+ loadWait?: number,
+): string {
+ return assemble(
+ `Loaded files: ${formatInteger(loadFiles)}`,
+ loadBytes != null && `Loaded bytes: ${formatBytesCompact(loadBytes)}`,
+ loadTime != null && loadTime > 0 && `Load time: ${formatDurationWithMs(loadTime)}`,
+ loadTime && loadBytes
+ ? `Load rate: ${formatByteRate(loadBytes / (loadTime / 1000))}`
+ : undefined,
+ loadWait != null && loadWait > 0 && `Load wait: ${formatDurationWithMs(loadWait)}`,
+ ).join('\n');
+}
+
function inputLabelContent(stage: StageDefinition, inputIndex: number) {
const { input, broadcast } = stage.definition;
const stageInput = input[inputIndex];
@@ -337,6 +355,22 @@ export const ExecutionStagesPane = React.memo(function ExecutionStagesPane(
/>
>
)}
+ {Boolean(c.loadFiles) && (
+ <>
+ {' '}
+ {' '}
+