Skip to content

perf(map): optimize deck.gl rendering pipeline — supercluster config, viewport caching, data windowing#2669

Open
dx0rz wants to merge 6 commits intokoala73:mainfrom
dx0rz:main
Open

perf(map): optimize deck.gl rendering pipeline — supercluster config, viewport caching, data windowing#2669
dx0rz wants to merge 6 commits intokoala73:mainfrom
dx0rz:main

Conversation

@dx0rz
Copy link
Copy Markdown

@dx0rz dx0rz commented Apr 4, 2026

Summary

Optimize the DeckGL map rendering pipeline by:

  • tuning supercluster configuration for the four marker layers,
  • adding a zoom‑adaptive cluster radius helper, and
  • windowing large datasets to the current viewport to avoid off‑screen work.

This reduces redundant cluster recalculations and JS‑side processing during
map panning/zooming, especially for large datasets (FIRMS fires, UCDP events).

Type of change

  • Refactor / code cleanup
  • Performance optimization
  • Bug fix
  • New feature
  • New data source / feed
  • New map layer
  • Documentation
  • CI / Build / Infrastructure

Affected areas

  • Map / Globe
  • News panels / RSS feeds
  • AI Insights / World Brief
  • Market Radar / Crypto
  • Desktop app (Tauri)
  • API endpoints (/api/*)
  • Config / Settings
  • Other:

Changes

1. Supercluster configuration (DeckGLMap.ts)

  • Increased base radii across 4 cluster types:
    • Protests: 60 → 80 px
    • Tech HQs: 50 → 70 px
    • Tech Events: 50 → 65 px
    • Datacenters: 70 → 90 px
  • Raised maxZoom from 14 → 16 so the cluster index can resolve to
    individual markers at city‑level zoom without forcing a full layer rebuild.

2. Dynamic cluster radius helper

  • Added getDynamicClusterRadius(zoom, baseRadius) (exported helper) that
    scales the effective cluster radius by zoom tier:

    • zoom <= 21.5 × baseRadius (world overview, aggressive merging)
    • 3–41.25 × baseRadius (continental)
    • 5–91.0 × baseRadius (normal operation)
    • >= 100.75 × baseRadius (finer detail in city views)

This keeps marker counts bounded at overview zoom while still fanning clusters
out smoothly when zooming in.

3. Viewport windowing for large datasets

  • Added a private filterToViewport(items, bounds, { margin, minItems }) helper:
    • Applies a ±20% margin around the current viewport.
    • Only runs when items.length >= 200 to avoid overhead on small arrays.
  • Wired into:
    • NASA FIRMS fires
    • UCDP conflict events

This avoids iterating over and rendering global arrays when the user is focused
on a single region.

4. Viewport cluster cache key coarsening

  • Relaxed the viewport hash from 4 decimal places (~11 m) to 2 decimal places
    (~1.1 km) when caching cluster results.
  • This removes redundant getClusters() calls during sub‑kilometre pans and
    smooth animation, while keeping cluster layouts stable at human map scales.

Tests

  • Added tests/deckgl-map-perf.test.mjs with 12 tests:

    • 6 for getDynamicClusterRadius (tier boundaries, rounding behaviour).
    • 6 for filterToViewport (threshold bypass, global passthrough, regional
      subsets, 20% margin behaviour, null bounds, and out‑of‑bounds rejection).
  • npm run typecheck

  • node --import tsx --test tests/deckgl-map-perf.test.mjs

Screenshots

N/A – behaviour is performance‑related and visible as smoother panning/zooming
rather than UI changes.

Copilot AI and others added 4 commits April 4, 2026 05:31
…rmance

perf(map): optimize deck.gl rendering pipeline — supercluster config, viewport caching, data windowing
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 4, 2026

@dx0rz is attempting to deploy a commit to the Elie Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added the trust:caution Brin: contributor trust score caution label Apr 4, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 4, 2026

Greptile Summary

This PR optimizes the deck.gl rendering pipeline by tuning supercluster radii/maxZoom, adding a viewport cache key coarsening, and windowing FIRMS/UCDP datasets to the visible region. Two P1 issues need attention before merge:

  • getDynamicClusterRadius is exported and tested but never called — Supercluster still receives hard-coded radii at construction time, so the zoom-adaptive scaling has no runtime effect.
  • filterToViewport does not handle antimeridian-crossing viewports: points stored with canonical longitudes (e.g. lon=-170) are silently dropped when getBounds() returns an extended east >180 (Pacific Ocean view).

Confidence Score: 4/5

Not safe to merge as-is — one claimed optimization is inert (dead code) and the viewport filter can silently drop data in Pacific-region views.

Two P1 findings: (1) getDynamicClusterRadius is never called so the zoom-adaptive radius feature ships as dead code, and (2) filterToViewport lacks antimeridian handling, silently discarding valid fire/conflict data for Pacific-region viewports. Both are correctness defects in the changed code paths.

src/components/DeckGLMap.ts — wire getDynamicClusterRadius into the cluster rebuild path and add antimeridian-safe longitude comparison in filterToViewport.

Important Files Changed

Filename Overview
src/components/DeckGLMap.ts Adds getDynamicClusterRadius (exported but never called — dead code), filterToViewport (correctly wired for FIRMS/UCDP but missing antimeridian handling), coarser viewport cache key, and increased supercluster radii/maxZoom. Two P1 issues: the helper is inert at runtime, and the viewport filter silently drops Pacific-region data.
tests/deckgl-map-perf.test.mjs 12 well-structured unit tests for the two new helpers; logic is correct but getDynamicClusterRadius is replicated instead of imported, and no antimeridian-crossing test case is included.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[buildLayers called] --> B[filterByTimeCached for FIRMS fires]
    B --> C[filterToViewport — viewport windowing]
    C --> D{items.length >= 200?}
    D -- No --> E[Return all items unchanged]
    D -- Yes --> F[getBounds from maplibreMap]
    F --> G{bounds available?}
    G -- No --> E
    G -- Yes --> H[Compute ±20% lon/lat margin]
    H --> I{lon crosses antimeridian?}
    I -- Yes, w>e or e>180 --> J[⚠️ Filter may reject valid points]
    I -- No --> K[Filter items inside expanded bbox]
    K --> L[Filtered dataset passed to deck.gl layer]

    M[updateClusterData called] --> N[Get integer zoom + boundsKey 2dp]
    N --> O{zoom, boundsKey, layerMask unchanged?}
    O -- Yes --> P[Skip — cache hit]
    O -- No --> Q[getClusters for each SC layer]
    Q --> R[Static radius from construction]
    S[getDynamicClusterRadius] -.->|Exported but never called| R
Loading

Reviews (1): Last reviewed commit: "Merge pull request #1 from dx0rz/copilot..." | Re-trigger Greptile

…port, import in tests

Agent-Logs-Url: https://github.com/dx0rz/worldmonitor/sessions/4b1317cb-bdc9-4ab2-8c8a-0b6941882b66

Co-authored-by: dx0rz <109863805+dx0rz@users.noreply.github.com>
@dx0rz
Copy link
Copy Markdown
Author

dx0rz commented Apr 4, 2026

Thanks for the automated review from Greptile — the three findings should now be addressed:

  • getDynamicClusterRadius is no longer dead code: it has been extracted to
    src/utils/cluster-radius.ts, and updateClusterData() now uses it to
    select zoom tiers and rebuild the active supercluster instances when the
    tier changes. All rebuild*Supercluster helpers pass the dynamic radius
    instead of hard‑coded values.
  • filterToViewport now handles antimeridian‑crossing viewports correctly,
    so FIRMS/UCDP points near ±180° are no longer dropped when the map crosses
    the date line.
  • The perf tests import getDynamicClusterRadius from the shared utility and
    include a new antimeridian test case to cover the Pacific‑region scenario.

These changes are in commit fix(map): wire getDynamicClusterRadius, fix antimeridian filterToViewport, import in tests (d800ac6). I’m happy to tweak
anything further if you’d prefer a different approach to the zoom tiers or
viewport filtering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trust:caution Brin: contributor trust score caution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants