From 06cc77fdec636d4d35e7a6b1bf76c59c6c0ae736 Mon Sep 17 00:00:00 2001 From: 4aiman Date: Tue, 29 Sep 2026 15:49:02 +0300 Subject: [PATCH] Maps: trim tile retention, simplify big tracks by zoom, thin POIs when zoomed out Canvas (prev commit) made the big-track map self-recover but the Chromium compositor still hit 'tile memory limits exceeded' ~46x and 10k segments still janked. Three cheap levers: - tilecache: keepBuffer 2->1 and updateWhenZooming:false - fewer retained off-screen tiles in the compositor's raster budget on a high-DPI screen. - track/roads polylines: smoothFactor 2.5 (Douglas-Peucker in pixels) - a 10k-point track draws far fewer segments zoomed out, full detail zoomed in. - POI: cap markers by zoom (z>=16:500, 15:200, 14:80, 13:30) instead of a flat 500 - a handful near min-zoom, everything only when zoomed in close. --- .../2026-09-29_startup-slowness.md | 23 +++++++++++++++++++ frontend/js/main.js | 9 +++++--- frontend/js/poi.js | 8 +++++-- frontend/js/tilecache.js | 7 ++++++ 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/docs/session-logs/2026-09-29_startup-slowness.md b/docs/session-logs/2026-09-29_startup-slowness.md index 4db9eb4..1d631a1 100644 --- a/docs/session-logs/2026-09-29_startup-slowness.md +++ b/docs/session-logs/2026-09-29_startup-slowness.md @@ -73,3 +73,26 @@ reopen -> убрал достройку -> зум/таскание; буфер Проверка: воспроизвести зум/таскание на треке 60км и на карте дорог, снять logcat, убедиться, что `tile memory limits exceeded` больше НЕ появляется, тайлы держатся. + +### Итог проверки canvas (build 479) - помог частично +Пользователь воспроизвёл на 479: "подвисло, но восстановилось" (раньше - только force-stop). +Снял logcat + инспекция живой страницы через CDP (`test_recovery/cdp.js`, +`adb forward ... webview_devtools_remote_`): +- Canvas ПРИМЕНИЛСЯ: в DOM детали `svgPaths=0`, оверлей - canvas. +- Но `tile_manager tile memory limits exceeded` всё равно ~46 раз (столько же). Значит бюджет + растровых тайлов компоновщика забивают САМИ тайлы карты (высокий DPI: 1260 физ / 404 css ≈ 3x) + + объём трека, а не SVG. Canvas дал живучесть (само восстанавливается), но джанк от 10865 + сегментов остался. + +### Догоняющие правки (по решению пользователя: урезать тайлы + меньше точек на зум-ауте + POI) +1. `tilecache.js` - у тайл-слоя `keepBuffer: 1` (было 2) и `updateWhenZooming: false`: меньше + офскрин-тайлов в памяти компоновщика, тайлы не грузятся в процессе зума. +2. `main.js` - `smoothFactor: 2.5` на главных полилиниях трека (деталь, `showSessionDetail`) и + на сегментах карты дорог (`showRoadsMap`). smoothFactor - допуск Дугласа-Пекера в ПИКСЕЛЯХ, + поэтому сам прореживает: при зум-ауте точки сходятся в пиксели и выбрасываются (меньше + сегментов), при зум-ине - полная детализация. Ровно "меньше точек на сильном зум-ауте". +3. `poi.js` - кап маркеров POI масштабируется зумом (z>=16: 500, 15: 200, 14: 80, 13: 30): + на сильном зум-ауте показываем горстку ближайших, а не всё подряд. + +Проверка: воспроизвести тот же сценарий, снять logcat - ожидаем, что `tile memory limits +exceeded` резко упадёт/исчезнет, джанк уйдёт; POI на малом зуме - мало маркеров. diff --git a/frontend/js/main.js b/frontend/js/main.js index f4f91ec..6e87eb9 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -5675,8 +5675,11 @@ async function showSessionDetail(sessionId) { let allCoords = []; segments.forEach(seg => { if (seg.length < 2) { allCoords.push(...seg); return; } - L.polyline(seg, { color: "#ffffff", weight: 8, opacity: 0.8 }).addTo(map); - L.polyline(seg, { color: GPS.config.trackColor || "#bb86fc", weight: 5 }).addTo(map); + // smoothFactor: Douglas-Peucker tolerance in PIXELS, so it drops points that collapse + // together on screen - full detail zoomed in, far fewer segments when zoomed out (where + // a 10k-point track otherwise janks and floods the compositor). 2.5px is imperceptible. + L.polyline(seg, { color: "#ffffff", weight: 8, opacity: 0.8, smoothFactor: 2.5 }).addTo(map); + L.polyline(seg, { color: GPS.config.trackColor || "#bb86fc", weight: 5, smoothFactor: 2.5 }).addTo(map); L.circleMarker(seg[0], { radius: 5, color: "#4caf50", fillColor: "#4caf50", fillOpacity: 1 }).addTo(map); L.circleMarker(seg[seg.length - 1], { radius: 5, color: "#f44336", fillColor: "#f44336", fillOpacity: 1 }).addTo(map); allCoords.push(...seg); @@ -8458,7 +8461,7 @@ async function showRoadsMap() { let allCoords = []; for (let s of segments) { let color = roadColor(s.atype); - L.polyline(s.coords, { color, weight: 4, opacity: 1 }).addTo(map); + L.polyline(s.coords, { color, weight: 4, opacity: 1, smoothFactor: 2.5 }).addTo(map); // px-space simplify: fewer points zoomed out allCoords.push(...s.coords); } diff --git a/frontend/js/poi.js b/frontend/js/poi.js index 6caa6d0..51497bd 100644 --- a/frontend/js/poi.js +++ b/frontend/js/poi.js @@ -49,7 +49,11 @@ function render() { group.clearLayers(); - if (!shown || map.getZoom() < MINZOOM || !POI._data) return; + let z = map.getZoom(); + if (!shown || z < MINZOOM || !POI._data) return; + // Fewer markers the further you zoom out: a wide view spans too many POIs to read (and to + // draw). Scale the cap with zoom - a handful near MINZOOM, the full CAP once zoomed in. + let cap = z >= 16 ? CAP : z >= 15 ? 200 : z >= 14 ? 80 : 30; let b = map.getBounds(), n = 0; for (let i = 0; i < POI._data.length; i++) { let p = POI._data[i]; @@ -59,7 +63,7 @@ let c = CATS[p.c] || { l: p.c }; m.bindPopup((p.n ? "" + p.n + "
" : "") + c.l); group.addLayer(m); - if (++n >= CAP) break; + if (++n >= cap) break; } } map.on("moveend zoomend", render); diff --git a/frontend/js/tilecache.js b/frontend/js/tilecache.js index fb07f84..69ec187 100644 --- a/frontend/js/tilecache.js +++ b/frontend/js/tilecache.js @@ -127,6 +127,13 @@ TileCache.downloadArea = async function(bounds, zoomMin, zoomMax, onProgress) { // Custom Leaflet TileLayer that checks IndexedDB first TileCache.createLayer = function() { return L.TileLayer.extend({ + options: { + // Keep fewer off-screen tile rings and don't reload tiles mid-zoom: on a high-DPI + // screen the compositor's raster-tile budget (cc/tiles "tile memory limits exceeded") + // is filled by the map tiles themselves, so trimming retained tiles keeps content drawing. + keepBuffer: 1, // default 2 + updateWhenZooming: false, // defer tile loads until the zoom gesture settles + }, createTile: function(coords, done) { const tile = document.createElement("img"); const key = `${coords.z}/${coords.x}/${coords.y}`;