perf: geocode pipeline — batch POST + parallel server, 200→1 roundtrip
JS preload(): replaced N individual GET /api/geocode (concurrency 2) with a single POST /api/geocode/batch — one HTTP roundtrip instead of up to N/2 sequential ones. schedLoc debounce reduced 600→200ms. Server geocode_batch(): ThreadPoolExecutor(max_workers=4) parallelises Nominatim/reverse_geocoder calls instead of sequential loop. Deduplicates coords before submitting futures. lru_cache absorbs duplicates within batch. Pi geocode_batch_route(): deduplicate coords, removed stale 'if label:' guard (label always non-empty after BUG-13 fix).
This commit is contained in:
+18
-17
@@ -75,31 +75,32 @@
|
||||
function preload(pts) {
|
||||
if (_geoCtrl) _geoCtrl.abort();
|
||||
_geoCtrl = new AbortController(); var sig = _geoCtrl.signal; _cache = {};
|
||||
var seen = {}, q = [], i;
|
||||
var seen = {}, coords = [], i;
|
||||
for (i = 0; i < pts.length; i++) {
|
||||
var k = gk(pts[i].latitude, pts[i].longitude);
|
||||
if (!k || seen[k]) continue; seen[k] = 1;
|
||||
q.push({k: k, lat: pts[i].latitude, lon: pts[i].longitude});
|
||||
coords.push({lat: pts[i].latitude, lon: pts[i].longitude});
|
||||
}
|
||||
if (!q.length) return;
|
||||
var C = 2, idx = 0;
|
||||
function nx() {
|
||||
if (idx >= q.length || sig.aborted) return;
|
||||
var it = q[idx++], c = new AbortController();
|
||||
var t = setTimeout(function () { c.abort(); }, 3000);
|
||||
sig.addEventListener("abort", function () { c.abort(); });
|
||||
fetch("/api/geocode?lat=" + it.lat + "&lon=" + it.lon, {signal: c.signal})
|
||||
.then(function (r) { clearTimeout(t); return r.ok ? r.json() : null; })
|
||||
.then(function (d) { if (!sig.aborted) _cache[it.k] = (d && d.label) || null; })
|
||||
.catch(function () { clearTimeout(t); })
|
||||
.finally(function () { if (!sig.aborted) nx(); });
|
||||
}
|
||||
for (var j = 0; j < C && j < q.length; j++) nx();
|
||||
if (!coords.length) return;
|
||||
// Single batch POST instead of N individual GETs — one roundtrip.
|
||||
fetch("/api/geocode/batch", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({coords: coords}),
|
||||
signal: sig
|
||||
})
|
||||
.then(function (r) { return r.ok ? r.json() : {}; })
|
||||
.then(function (data) {
|
||||
if (sig.aborted) return;
|
||||
for (var key in data) { if (data.hasOwnProperty(key)) _cache[key] = data[key]; }
|
||||
})
|
||||
.catch(function () {});
|
||||
}
|
||||
function showLoc(lat, lon) {
|
||||
var k = gk(lat, lon); if (!k || k === _lastKey) return; _lastKey = k;
|
||||
var fb = lat.toFixed(5) + ", " + lon.toFixed(5);
|
||||
if (_cache.hasOwnProperty(k)) { locEl.textContent = _cache[k] || fb; return; }
|
||||
// Fallback: individual fetch only if preload didn't cover this coord.
|
||||
var c = new AbortController();
|
||||
var t = setTimeout(function () { c.abort(); }, 3000);
|
||||
fetch("/api/geocode?lat=" + lat + "&lon=" + lon, {signal: c.signal})
|
||||
@@ -112,7 +113,7 @@
|
||||
}
|
||||
function schedLoc(lat, lon) {
|
||||
clearTimeout(_geoTimer);
|
||||
_geoTimer = setTimeout(function () { showLoc(lat, lon); }, 600);
|
||||
_geoTimer = setTimeout(function () { showLoc(lat, lon); }, 200);
|
||||
}
|
||||
|
||||
// ── Format ───────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user