Skip to content

perf: chunk the mobile SVG-map render into yielded <50ms tasks (cut TBT — #4431 deferral didn't) #4442

Description

@koala73

Why

Follow-up to #4429/#4431. PR #4431 deferred the mobile SVG-map dynamic-overlay render off first paint via scheduleAfterFirstPaint. Validated on prod (2026-06-26, mobile Lighthouse ×3): Map-*.js boot scripting dropped 1277 ms → ~880 ms (−30%) — but mobile Perf stayed ~65 and TBT ~1477 ms (both within noise).

Root cause of the non-movement: scheduleAfterFirstPaint reorders the overlay render off first paint (helps FCP/perceived load) but the deferred work still executes as a single long task within Lighthouse's TBT window (FCP→TTI). TBT = Σ(task − 50 ms) over tasks > 50 ms — moving one ~390 ms long task later doesn't reduce it. To cut TBT you must break the long render task into sub-50 ms chunks, not just reorder it.

Scope

src/components/Map.ts render() — the mobile/fallback D3/SVG renderer. The base block (countries/grid/graticule) and the dynamic block (cables/pipelines/conflicts/AIS + renderClusterLayer + renderOverlays) each run synchronously as part of one render task.

Approach (directional)

  • Break render()'s dynamic-overlay pass into per-layer steps that yield to the main thread between layers (e.g., await a microtask/scheduler.postTask/setTimeout(0) between renderCablesrenderPipelinesrenderConflictsrenderAisDensityrenderClusterLayerrenderOverlays), so no single task exceeds ~50 ms.
  • Consider the same for the base render if renderCountries (topojson path generation) is itself a >50 ms task.
  • Preserve correctness: a render started mid-yield must be cancelable/coalesced if a newer render is requested (reuse the existing renderScheduled/MIN_RENDER_INTERVAL_MS machinery + the destroyed guard added in perf(map): defer mobile SVG-map dynamic overlays off the first-paint path (#4429) #4431).
  • Measure-first: instrument the per-layer task durations to confirm which layers exceed 50 ms before chunking.

Acceptance

  • No single map-render task > ~50 ms in a mobile DevTools performance trace.
  • Prod mobile Lighthouse TBT improves vs the ~1477 ms baseline (median of ≥3).
  • All layers still render; zoom/pan/toggle/theme interactions remain correct (no torn/partial overlays).

Note

Deferral (#4431) addressed perceived-load; this addresses the score/TBT by reducing long-task duration. See the validation in #4429 comments + the 2026-06-26 measurement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions