Summary
JobDetail.tsx retains at most MAX_LOSS_POINTS = 2000 loss points using next.slice(next.length - MAX_LOSS_POINTS) (~L223-235). That is a sliding window: once a run emits more than 2000 loss frames, the OLDEST points are dropped, so the chart loses the beginning of the loss curve — exactly the region that shows initial convergence and where most of the loss delta lives. The stats and the visual shape of the run change silently mid-training.
Where
packages/studio-app/src/pages/JobDetail.tsx ~L27 (MAX_LOSS_POINTS), ~L223-235 (the setPoints updater).
- The cap itself is justified (the comment is right that 2000 exceeds visual resolution and bounds re-render cost) — the problem is only which points are kept.
Proposal
Keep the bound, change the eviction: when the cap is reached, compact by bucketed downsampling instead of dropping the head — e.g. stride-doubling (compact to ~cap/2 representatives, keep appending), with bucket representatives chosen so that (a) points carrying the sparse evalLoss series survive preferentially, (b) local min/max survive so spikes stay visible, (c) the first and last points always survive. Output stays sorted by step, so LossChart's binary-search tooltip (~L240-251, the O(log n) hover lookup) is unaffected.
This keeps memory and render cost identical (still ≤ 2000 points) while the chart shows the whole run at progressively coarser resolution — the standard trade for training dashboards.
(A PR implementing this as a pure, unit-tested helper module is ready to follow this issue.)
Summary
JobDetail.tsxretains at mostMAX_LOSS_POINTS = 2000loss points usingnext.slice(next.length - MAX_LOSS_POINTS)(~L223-235). That is a sliding window: once a run emits more than 2000 loss frames, the OLDEST points are dropped, so the chart loses the beginning of the loss curve — exactly the region that shows initial convergence and where most of the loss delta lives. The stats and the visual shape of the run change silently mid-training.Where
packages/studio-app/src/pages/JobDetail.tsx~L27 (MAX_LOSS_POINTS), ~L223-235 (thesetPointsupdater).Proposal
Keep the bound, change the eviction: when the cap is reached, compact by bucketed downsampling instead of dropping the head — e.g. stride-doubling (compact to ~cap/2 representatives, keep appending), with bucket representatives chosen so that (a) points carrying the sparse
evalLossseries survive preferentially, (b) local min/max survive so spikes stay visible, (c) the first and last points always survive. Output stays sorted bystep, soLossChart's binary-search tooltip (~L240-251, the O(log n) hover lookup) is unaffected.This keeps memory and render cost identical (still ≤ 2000 points) while the chart shows the whole run at progressively coarser resolution — the standard trade for training dashboards.
(A PR implementing this as a pure, unit-tested helper module is ready to follow this issue.)