perf(tracks): bound playback rendering work
This commit is contained in:
@@ -8,6 +8,14 @@ The 15-second monitor refresh previously treated every new response object as a
|
||||
|
||||
FleetMap now fingerprints only fields that affect map rendering. An unchanged refresh performs no AMap data/style/label mutation. A moving vehicle still updates MassMarks once, but the LabelsLayer removes and replaces only that vehicle's changed marker; full label-layer replacement is reserved for crossing the normal/dense zoom boundary. The selected ripple marker also skips redundant position writes. This uses the official AMap JS API 2.0 [`LabelsLayer.remove`](https://lbs.amap.com/api/javascript-api-v2/guide/amap-massmarker/label-marker) and `LabelMarker` update model instead of reconstructing all overlays. Unit tests assert zero map mutations for an `asOf`-only refresh and exactly one label replacement for one moved vehicle.
|
||||
|
||||
## 2026-07-16: bounded track-playback rendering
|
||||
|
||||
The production replay for a 1,600-point day contained 84 interactive activity segments, nine stop rows and 64 event rows. Advancing `activeIndex` previously rendered the complete query/result rail and all 84 segment buttons on every playback step. It also rebuilt `Intl.NumberFormat` and `Intl.DateTimeFormat` instances during render, counted passed map points with a full-array reduction, and at 4× speed started a 180 ms map pan every 75 ms. The overlapping camera animations and repeated static work competed with the marker update on the main thread.
|
||||
|
||||
Playback now precomputes sparse stop/event highlight indexes once per track. The memoized result rail receives a shared empty selection for ordinary points, while the memoized segment rail receives stable callbacks, so both static subtrees skip the vast majority of playback renders. Date and number formatters are module-level reusable instances, and the passed-path count is a precomputed O(1) lookup instead of an O(points) scan per step. Follow animation is cadence-bound: 4× playback uses 65 ms movement inside its 75 ms update interval, while direct operator selection retains the smoother 180 ms transition.
|
||||
|
||||
This follows React's requirement that memoized children receive stable props and callbacks, and the browser animation model that schedules work against paint frames and calculates progress from timestamps: <https://react.dev/reference/react/memo>, <https://react.dev/reference/react/useMemo>, <https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame>. The regression suite asserts sparse highlight mapping, the 55 ms minimum playback interval, 65 ms 4× follow duration, 180 ms paused duration, passed-path advancement and complete map/listener cleanup.
|
||||
|
||||
## 2026-07-16: single responsive mileage matrix
|
||||
|
||||
The mileage query rendered its desktop table and mobile card matrix at the same time, then hid one tree with CSS. A 90-day, 20-vehicle production page therefore retained 1,860 desktop cells and another 1,800 hidden mobile day cells. Chrome identifies excessive DOM size as a source of longer style calculation, layout and interaction work, and recommends creating nodes only when they are needed: <https://developer.chrome.com/docs/performance/insights/dom-size>, <https://web.dev/articles/dom-size-and-interactivity>.
|
||||
|
||||
Reference in New Issue
Block a user