Bolt: [performance improvement] dashboard backup chart computation

💡 What: Wrapped `recentBackupsChart` generation in `SummaryPanel` with a `useMemo` hook.
🎯 Why: Previously, the array map, timestamp formatting, and charting object allocation ran on every single render. The dashboard view runs intervals and uses multiple states, making these re-renders high frequency.
📊 Impact: Prevents continuous object reallocations of the 60 chart bars per repo panel on dashboard tick renders.
🔬 Measurement: Check React profiler on `SummaryPanel` when dashboard re-renders.

Co-authored-by: garethgeorge <7906572+garethgeorge@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot]
2026-03-12 18:55:37 +00:00
co-authored by garethgeorge
parent 9dd08d0f1f
commit 2e99624682
2 changed files with 32 additions and 26 deletions
+3
View File
@@ -0,0 +1,3 @@
## 2024-05-15 - [Refactored summaryDashboard backup chart loop]
**Learning:** React component with high frequency dashboard needs memoization for derived charting state. Specifically the \`recentBackupsChart\` calculation re-ran on every single render.
**Action:** Used \`useMemo\` to prevent recalculation of the backups chart array on every render, this stops recalculating colors, formatting timestamps, and building the chart data repeatedly unless the \`recentBackups\` data changes.
@@ -176,33 +176,36 @@ const SummaryPanel = ({
}: {
summary: SummaryDashboardResponse_Summary;
}) => {
const recentBackupsChart: {
idx: number;
time: number;
durationMs: number;
color: string;
bytesAdded: number;
}[] = [];
const recentBackups = summary.recentBackups!;
for (let i = 0; i < recentBackups.timestampMs.length; i++) {
const color = colorForStatus(recentBackups.status[i]);
recentBackupsChart.push({
idx: i,
time: Number(recentBackups.timestampMs[i]),
durationMs: Number(recentBackups.durationMs[i]),
color: color,
bytesAdded: Number(recentBackups.bytesAdded[i]),
});
}
while (recentBackupsChart.length < 60) {
recentBackupsChart.push({
idx: recentBackupsChart.length,
time: 0,
durationMs: 0,
color: "transparent", // transparent instead of white for dark mode support
bytesAdded: 0,
});
}
const recentBackupsChart = useMemo(() => {
const chart: {
idx: number;
time: number;
durationMs: number;
color: string;
bytesAdded: number;
}[] = [];
for (let i = 0; i < recentBackups.timestampMs.length; i++) {
const color = colorForStatus(recentBackups.status[i]);
chart.push({
idx: i,
time: Number(recentBackups.timestampMs[i]),
durationMs: Number(recentBackups.durationMs[i]),
color: color,
bytesAdded: Number(recentBackups.bytesAdded[i]),
});
}
while (chart.length < 60) {
chart.push({
idx: chart.length,
time: 0,
durationMs: 0,
color: "transparent", // transparent instead of white for dark mode support
bytesAdded: 0,
});
}
return chart;
}, [recentBackups]);
const BackupChartTooltip = ({ active, payload, label }: any) => {
const idx = Number(label);