perf: group the timeline's lanes in one pass
Stacking by game rebuilt a lane's whole array for every row it added, which is quadratic in the lane's length. That is cheap at three events and not at a reader with fourteen games switched on and the future plotted — and it is not paid once, because the board re-renders on every clock tick. Appending into the array instead is the same output: `Map` preserves insertion order, so lanes still arrive in the order their first row did and the rows inside one keep the order they were given, which is what the existing tests pin. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4fe563dcbb
commit
1e7a7abc64
@@ -97,9 +97,15 @@ export function timelineLanes<T extends Row>(
|
|||||||
return [{ id: "all", game: null, rows: [...rows].sort(order) }];
|
return [{ id: "all", game: null, rows: [...rows].sort(order) }];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Appended into rather than rebuilt per row: the copy-and-reset form this
|
||||||
|
// replaced was quadratic in a lane's length, and it runs on every render of a
|
||||||
|
// board that redraws each second. `Map` keeps insertion order, so the lanes
|
||||||
|
// still arrive in the order their first row did.
|
||||||
const byGame = new Map<LaneId, T[]>();
|
const byGame = new Map<LaneId, T[]>();
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
byGame.set(row.event.game, [...(byGame.get(row.event.game) ?? []), row]);
|
const lane = byGame.get(row.event.game);
|
||||||
|
if (lane === undefined) byGame.set(row.event.game, [row]);
|
||||||
|
else lane.push(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lanes = [...byGame];
|
let lanes = [...byGame];
|
||||||
|
|||||||
Reference in New Issue
Block a user