Poser le filtre du fond OSM sur la couche et réduire la réserve de tuiles LiDAR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -40,6 +40,7 @@
|
|||||||
- **Carte autonome (Pi sans worker)** : amont (`LIDAR_SOURCE_URL`/`LIDAR_MAPS_URL`) éteint ⇒ la carte reste servie depuis le disque. `_remote_payload` mémorise aussi l'échec (TTL 60 s, délai 10 s : sinon chaque requête repayait le délai réseau et `/api/map/meta` ne répondait plus), puis l'index local (`_build_index`) prend le relais ; coupe-circuits sur les sources (`_SOURCE_OFFLINE`, 60 s) et les tuiles (`_UPSTREAM`, réarmé à expiration) ; source rapatriée datée à sa version amont (`os.utime`) pour que l'index local garde les mêmes dates ; pas de requête amont pour une tuile sans dalle quand l'inventaire vient de l'amont. En cache seule, une tuile périmée reste servie (`no-store`, `X-Tile-Pending`) en attendant la nouvelle.
|
- **Carte autonome (Pi sans worker)** : amont (`LIDAR_SOURCE_URL`/`LIDAR_MAPS_URL`) éteint ⇒ la carte reste servie depuis le disque. `_remote_payload` mémorise aussi l'échec (TTL 60 s, délai 10 s : sinon chaque requête repayait le délai réseau et `/api/map/meta` ne répondait plus), puis l'index local (`_build_index`) prend le relais ; coupe-circuits sur les sources (`_SOURCE_OFFLINE`, 60 s) et les tuiles (`_UPSTREAM`, réarmé à expiration) ; source rapatriée datée à sa version amont (`os.utime`) pour que l'index local garde les mêmes dates ; pas de requête amont pour une tuile sans dalle quand l'inventaire vient de l'amont. En cache seule, une tuile périmée reste servie (`no-store`, `X-Tile-Pending`) en attendant la nouvelle.
|
||||||
- **Pyramide téléchargée en tâche de fond** : avec `LIDAR_MAPS_URL`, la maintenance (`_bg_process_one`) TÉLÉCHARGE les tuiles des niveaux stockés depuis l'amont (stat `telechargees`), sans attendre l'affichage ; rendu local en repli si l'amont ne répond pas.
|
- **Pyramide téléchargée en tâche de fond** : avec `LIDAR_MAPS_URL`, la maintenance (`_bg_process_one`) TÉLÉCHARGE les tuiles des niveaux stockés depuis l'amont (stat `telechargees`), sans attendre l'affichage ; rendu local en repli si l'amont ne répond pas.
|
||||||
- **Première apparition des dalles (`_apply_seen`, `index_xyz/.sources_seen.json`)** : date effective d'une source = max(version, première entrée dans l'inventaire). Une dalle écrite avant mais inventoriée après une tuile (TTL de l'index amont, anti-rebond de l'inventaire) périme donc la tuile — sinon trou permanent à ce niveau, sur disque, en mémoire et dans le navigateur (stamp `?v=` inchangé). Registre persistant ; absent avec un cache existant (mise à jour) ⇒ tout est périmé une fois.
|
- **Première apparition des dalles (`_apply_seen`, `index_xyz/.sources_seen.json`)** : date effective d'une source = max(version, première entrée dans l'inventaire). Une dalle écrite avant mais inventoriée après une tuile (TTL de l'index amont, anti-rebond de l'inventaire) périme donc la tuile — sinon trou permanent à ce niveau, sur disque, en mémoire et dans le navigateur (stamp `?v=` inchangé). Registre persistant ; absent avec un cache existant (mise à jour) ⇒ tout est périmé une fois.
|
||||||
|
- **Coût navigateur de la carte (mesuré sous Chrome, Intel Iris Xe)** : le filtre d'assombrissement du fond OSM (`.base-dark`) est posé sur le **conteneur** de la couche, jamais sur chaque tuile — rendu identique (opérations par pixel), processus GPU 92 % → 56 % en déplacement et 99 % → 53 % au zoom molette. Couches LiDAR en `keepBuffer: 1` (tuiles 512 px = 1 Mo décodé chacune). Mesuré sans effet notable : `backdrop-filter` des cartes, `isolation`/`mix-blend-mode` en « normal », `will-change`. Tas JS 2-5 Mo, CPU au repos ~1 %. Décodage AVIF ~12 ms/tuile contre ~5 ms en WebP (compromis assumé : stockage AVIF).
|
||||||
- **Encodage AVIF rapide** : `AVIF_SPEED = 9` (`rendering.py`, `tiles.py`, `_SUBTILE_AVIF_SPEED` dans `index.py`) — dalle 5000 × 5000 px encodée en 0,6 s au lieu de 4 s (+3 % de taille, −0,3 dB) ; l'encodage était l'étape la plus longue du rendu d'une couche.
|
- **Encodage AVIF rapide** : `AVIF_SPEED = 9` (`rendering.py`, `tiles.py`, `_SUBTILE_AVIF_SPEED` dans `index.py`) — dalle 5000 × 5000 px encodée en 0,6 s au lieu de 4 s (+3 % de taille, −0,3 dB) ; l'encodage était l'étape la plus longue du rendu d'une couche.
|
||||||
- **Workers bornés par la VRAM** : chaque processus du pool prend une place fixe à sa création (`_init_worker_slot` dans `pipeline.py`, file multiprocessing) calculée par `gpu_worker_slots` (`gpu.py`) : au plus (VRAM libre − `LIDAR_GPU_RESERVE_MIB` 512) / `LIDAR_GPU_WORKER_MIB` (2048, pic estimé : contexte CUDA + calage conjoint CuPy en float64 + EDT de `_fill_nans`) workers par GPU, au moins un, entrelacés ; l'excédent tourne en CPU (`force_cpu`). L'ancien round-robin par numéro de fichier mettait 6 workers par RTX 5060 de 8 Go avec `LIDAR_WORKERS=auto` (12) : OOM. VRAM illisible (nvidia-smi en échec) : round-robin sans borne.
|
- **Workers bornés par la VRAM** : chaque processus du pool prend une place fixe à sa création (`_init_worker_slot` dans `pipeline.py`, file multiprocessing) calculée par `gpu_worker_slots` (`gpu.py`) : au plus (VRAM libre − `LIDAR_GPU_RESERVE_MIB` 512) / `LIDAR_GPU_WORKER_MIB` (2048, pic estimé : contexte CUDA + calage conjoint CuPy en float64 + EDT de `_fill_nans`) workers par GPU, au moins un, entrelacés ; l'excédent tourne en CPU (`force_cpu`). L'ancien round-robin par numéro de fichier mettait 6 workers par RTX 5060 de 8 Go avec `LIDAR_WORKERS=auto` (12) : OOM. VRAM illisible (nvidia-smi en échec) : round-robin sans borne.
|
||||||
- **Préparation sur GPU** : `_fill_nans` (transformée de distance `cupyx`) et les gradients de `SharedDEM` passent sur GPU quand il est actif (repli CPU). `NUMBA_CACHE_DIR=/tmp/numba-cache` (Dockerfile) évite la recompilation des noyaux numba à chaque worker.
|
- **Préparation sur GPU** : `_fill_nans` (transformée de distance `cupyx`) et les gradients de `SharedDEM` passent sur GPU quand il est actif (repli CPU). `NUMBA_CACHE_DIR=/tmp/numba-cache` (Dockerfile) évite la recompilation des noyaux numba à chaque worker.
|
||||||
|
|||||||
@ -172,8 +172,11 @@ html, body { height: 100%; overflow: hidden; background: var(--bg); color: var(-
|
|||||||
font: 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
|
font: 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
|
||||||
#map { position: absolute; inset: 0; background: var(--bg); }
|
#map { position: absolute; inset: 0; background: var(--bg); }
|
||||||
.leaflet-container { background: var(--bg); font: inherit; }
|
.leaflet-container { background: var(--bg); font: inherit; }
|
||||||
/* Fond OSM assombri pour laisser ressortir les rendus LiDAR. */
|
/* Fond OSM assombri pour laisser ressortir les rendus LiDAR. Filtre posé sur
|
||||||
.leaflet-tile-pane .leaflet-layer.base-dark .leaflet-tile { filter: brightness(0.38) contrast(1.1) saturate(0.7); }
|
le conteneur de la couche, pas sur chaque tuile : même rendu (opérations
|
||||||
|
par pixel), mais une seule passe de filtre au lieu d'une par tuile —
|
||||||
|
−30 % de CPU (moteur de rendu + GPU) en déplacement, mesuré sous Chrome. */
|
||||||
|
.leaflet-tile-pane .leaflet-layer.base-dark { filter: brightness(0.38) contrast(1.1) saturate(0.7); }
|
||||||
|
|
||||||
.card { position: fixed; z-index: 900; background: var(--card); color: var(--text);
|
.card { position: fixed; z-index: 900; background: var(--card); color: var(--text);
|
||||||
border: 1px solid var(--border); border-radius: var(--radius);
|
border: 1px solid var(--border); border-radius: var(--radius);
|
||||||
@ -604,7 +607,10 @@ function buildLayers() {
|
|||||||
maxNativeZoom: META.max_native_zoom,
|
maxNativeZoom: META.max_native_zoom,
|
||||||
minZoom: 0,
|
minZoom: 0,
|
||||||
maxZoom: 22,
|
maxZoom: 22,
|
||||||
keepBuffer: 2,
|
// Tuiles de 512 px : une rangée de réserve hors écran vaut les deux
|
||||||
|
// rangées de 256 px du fond. Deux rangées doublaient les images
|
||||||
|
// décodées gardées en mémoire (1 Mo chacune) pour peu de gain.
|
||||||
|
keepBuffer: 1,
|
||||||
updateWhenZooming: false,
|
updateWhenZooming: false,
|
||||||
crossOrigin: false,
|
crossOrigin: false,
|
||||||
errorTileUrl: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
|
errorTileUrl: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
|
||||||
|
|||||||
Reference in New Issue
Block a user