▶ CONTINUE 6/15 (drive speedup + P&R-NEC + OTP)
TL;DR
- Drive FIXED end-to-end: engine ~23s→~2s (res-8 OSRM coarsening) + res-8 OUTPUT for drive-containing requests (engine._collapse_to_res8) so the adapter builds ~15K not 107K features — public drive 500@121s → 200@~21s. No-modes byte-identical.
- P&R multi-station seeding (K=4 nearest railheads, engine._access_rail_seeds): Piscataway P&R now rides the NEC (New Brunswick/Edison ~70min) instead of nearest Dunellen Raritan Valley (~83). Validated vs OTP-NE oracle (geocoder:8091, OTP 2.6.0). World Cup ruled out (NEC identical across dates).
- ⭐ DO NEXT (user-prioritized): (1) <5s ADAPTER OPTIMIZATION — cache the static H3 cell→boundary ring + orjson in multimodal-adapter (the ~1ms/cell build is the remaining latency floor: drive ~21s, walk/transit ~15s). (2) ROBUST HOVER FIX — monkey-patch map.queryRenderedFeatures (onLoad) to filter missing layers; the deployed hasHex gate is only partial.
- GOTCHAS: purge stale res-9 drive caches on engine deploy (cache-first serves old 107K payloads); NEVER put proxy_read_timeout in the shared nginx snippet (mapnjt.conf duplicate); res-9 GeoJSON iso ~20MB EXCEEDS Mongo 16MB doc cap — store COMPACT not GeoJSON; precompute = lazy Mongo cache + warm head, NOT the full PB-scale cross-product.
CONTINUE — 2026-06-15 — MultiModal drive speedup + P&R-NEC + OTP validation
Host: geocoder (RTX 5080, 172.26.1.95) · GPU engine hexmap-api :8098 (systemd)
Live: https://multimodal.certihomes.com (geo2 .151; FE pm2 tlccommute :3000,
adapter pm2 multimodal-adapter :5055)
Repo: tlcengine/gpu-pilot @ 9346808 (pushed). Read first: memory
multimodal-fuel-drive-shipped.md, hexmap-api-interactive.md, then this.
⭐ DO THESE NEXT (user-prioritized, 2026-06-15)
1. <5s ADAPTER OPTIMIZATION (boundary cache + orjson)
The remaining latency floor. Engine is now ~2s, but the adapter builds ~14–15K
hex Features at ~1 ms/cell (~15–18s) — so drive ≈ 21s, walk/transit ≈ 15s. Fix in
/DataDrive/krish/krish/multimodal-adapter/adapter.py (geo2):
- Cache the static H3 cell→boundary ring — h3.cell_to_boundary is called per
cell every request (adapter.py _ring, ~line 346; loop ~line 454). The grid is
fixed, so memoize in a module-level dict (lazy, or warm res-8+res-9 at startup) →
per-request build becomes dict lookups, not h3 calls.
- Use orjson for the response dump (pip install orjson in the adapter venv
/home/krish/anaconda3; Flask Response(orjson.dumps(obj), mimetype=...)).
- Target: any mode <~5s. pm2 restart multimodal-adapter. Mirror final adapter.py to
gpu-pilot/multimodal/adapter-src/adapter.py.
2. ROBUST HOVER FIX (kill the hisochrone-fill console error for good)
Deployed Map.js has only the partial hasHex gate (Map.js:659) — it does NOT
cover the post-paint race, so Error: layer 'hisochrone-fill' does not exist …
queryRenderedFeatures can still flash on hover (react-map-gl@6 × maplibre@3 THROWS
on a missing layer). Bulletproof fix in /DataDrive/krish/krish/front-end/components/Map.js:
- Add a ref to <ReactMapGL> (~line 694; no ref/onLoad today) + an onLoad that
grabs mapRef.current.getMap() and monkey-patches map.queryRenderedFeatures
to filter options.layers to those that exist (map.getLayer(id)) and wrap in
try/catch → return []. Then hover never throws regardless of layer lifecycle.
- yarn build + pm2 restart tlccommute. Mirror to gpu-pilot/multimodal/fe-patches/Map.js.
- NOTE: users may be on a cached bundle — hard-refresh to pick up index-*.js.
DONE this session (2026-06-14 → 15) — all committed + live
- Drive engine ~10× faster (
modes.osrm_table_dest_to_cells_coarse,OSRM_DRIVE_RES=8): OSRM-table the ~15K res-8 PARENTS of candidate cells, fan time+distance_m to res-9. compute_ms ~23000 → ~2000. (engine.py/modes.py) - Drive serialization fix (
engine._collapse_to_res8, engine.py ~606/1139): any request containing a drive-family mode (drive/uber/pnr/knr) returns res-8 (~15K cells) not res-9 (~107K) → adapter no longer 500s. Public drive 500@121s → 200@~21s.out_resin response. Pure-transit stays res-9. No-modes byte-identical (core-hashcc034548…unchanged). - P&R multi-station seeding (
engine._access_rail_seeds,modes.PNR_N_STATIONS=4): seeds K=4 nearest railheads/cell (was single nearest) → multi-source RAPTOR picks the fastest LINE. Piscataway P&R now rides NEC (New Brunswick/Edison ~70 min), not nearest Dunellen Raritan Valley (~83). Validated vs OTP. - Timeout chain (geo2, NOT in repo): adapter
UPSTREAM_TIMEOUT30→120, gunicornworkers4→2, nginxproxy_read_timeout 130son multimodal/click+/geocode. - OTP-NE oracle stood up on geocoder:8091 (
java -Xmx24g -jar otp.jar --load /home/krish/otp-northeast --port 8091; OTP 2.6.0, graph.obj 2.6G, LegacyRestApi). Still running (pid was 1894099, 24G). 19-pair GPU-vs-OTP validation (multimodal/validate_otp.py): 11/19 within ±5 min; subway/LIRR/MNR/PATH/NEC-local all match; failures = no-Amtrak + transfer-choice + cross-date feed builds. - World Cup ruled out: NEC (Edison→Penn) identical 70 min/5 opts every date Jun 9 → Jul 22. Earlier "NEC broken" was the OLD/down OTP, not this fresh graph.
OTHER PENDING (after the two ⭐ above)
- Lazy Mongo isochrone cache (the durable latency fix): compute-on-first-click →
store COMPACT
{cell_id→time,cost,dist}(NOT GeoJSON; render geometry from static H3 grid on read; ~150 KB/res-8 doc) → instant on repeat. Warm top-N commute dests overnight. Evolve the existinghexmap-api/cache/*.json+hexmap-tiles/. Matches commute.tlcengine.com (multimodal/api-ref/Mongo+GeoJSON pattern). Do NOT brute-force the full cross-product (PB-scale; full precompute is days b/c drive/OSRM). - GPU cuGraph SSSP drive (sub-second): walk/bike already use cugraph_sssp; drive is the lone OSRM holdout. Needs a car-weighted tri-state OSM graph. May be MOOT if the adapter opt gets cold drive to ~5s.
- Expand OTP validation (more pairs; dig the Amtrak / optimistic-transfer clusters).
- National network toggles (Phase 2,
multimodal/RECON.md). - FE/adapter repo homes: geo2 FE remote = third-party Bitbucket (branch
routes); adapter has no remote → mirror to gpu-pilot (current durable path).
GOTCHAS (don't relearn)
- Stale res-9 drive caches must be PURGED on engine deploy — the cache-first
short-circuit serves old 107K payloads and the new res-8 path never runs. Clear
hexmap-api/cache/iso_*drive-family entries + the geo2 adapter cache after engine changes. - sudo pw file =
/home/krish/secert.txt(the typo'd name). Works for geo2 sudo too. - nginx: NEVER add
proxy_read_timeoutto the shared snippet/etc/nginx/snippets/proxy-headers.conf— it DUPLICATES one inmapnjt.conf→nginx -tfails. Put per-location in the multimodal site file. Backups →~/nginx-backups/. - res-9 GeoJSON iso (107K) ≈ 20 MB EXCEEDS MongoDB's 16 MB doc limit; res-8 ≈ 3 MB fits; store compact, not GeoJSON.
- OTP-NE plan:
/otp/routers/default/plan?fromPlace=lat,lon&toPlace=lat,lon&date=2026-06-17&time=8:00am&mode=TRANSIT,WALK.accessMode=car_park= the P&R reference. OTP-NE covers June 2026; GPU feed covers April (service_date 20260415) — cross-date weekday compare OK at ±few min. - Playwright =
/home/krish/gpu-pilot/hta/pwenv/bin/python; shots →multimodal/shots/. - geo2 = IP 172.26.1.151 (hostname doesn't resolve from geocoder).