Mettre à jour la pyramide pendant le rendu et réduire son stockage
Le pipeline régénère l'inventaire après chaque dalle par défaut (tous lanceurs, sauf --no-index), avec une passe différée quand l'anti-rebond ignore une dalle. La carte surveille l'inventaire toutes les 10 s et place les tuiles des dalles modifiées en tête de file de maintenance : la pyramide suit le rendu au lieu d'attendre la fin du lot. Stockage réduit pour le Raspberry Pi : seuls les niveaux standard pairs jusqu'à z16 sont écrits sur disque, en AVIF ; les autres, dont le niveau le plus fin (~75 % de la pyramide), sont rendus à la volée avec un cache mémoire, y compris en mode cache seule. L'interface ne demande que les niveaux pairs et réduit ceux du niveau supérieur aux zooms impairs. Mesuré sur 8 dalles : ~24 Mo de pyramide avant, 1,2 Mo après. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -28,6 +28,13 @@ TILE_SIZE = 256 # taille canonique (OSM/XYZ) ; @2x → 512
|
||||
TILE_MIN_Z = 5
|
||||
TILE_MAX_NATIVE_Z = 19 # 0,2 m/px ≈ résolution du z19 à la latitude 47°
|
||||
TILE_DIRNAME = "index_xyz" # cache disque, sous le dossier de sortie
|
||||
# Stockage réduit (petite machine) : niveaux exprimés en numérotation OSM
|
||||
# standard (tuile 256 px ; une tuile @2x de niveau z vaut une 256 px de z+1).
|
||||
# Seuls les niveaux PAIRS jusqu'à LIDAR_TILE_CACHE_MAX_Z sont écrits sur
|
||||
# disque ; les autres sont rendus à la volée (cache mémoire borné). Mesuré sur
|
||||
# 8 dalles : ~24 Mo → ~1 Mo de pyramide, le niveau le plus fin pesant ~75 %.
|
||||
TILE_CACHE_MAX_Z = int(os.environ.get("LIDAR_TILE_CACHE_MAX_Z", "16") or 16)
|
||||
TILE_EVEN_LEVELS = os.environ.get("LIDAR_TILE_EVEN_LEVELS", "1").strip() != "0"
|
||||
WEBP_QUALITY = 78
|
||||
AVIF_QUALITY = 60
|
||||
AVIF_SPEED = 9 # encodage rapide (cf. rendering.AVIF_SPEED : ×7, +3 % de taille)
|
||||
@ -745,6 +752,41 @@ def _write_atomic(path, data):
|
||||
tmp.unlink(missing_ok=True)
|
||||
|
||||
|
||||
def zoom_cached(z, scale=1):
|
||||
"""Vrai si les tuiles de ce niveau sont stockées sur disque."""
|
||||
zc = z + (1 if scale == 2 else 0)
|
||||
if zc > TILE_CACHE_MAX_Z:
|
||||
return False
|
||||
return not (TILE_EVEN_LEVELS and zc % 2)
|
||||
|
||||
|
||||
# Tuiles rendues à la volée (niveaux non stockés) : cache mémoire borné,
|
||||
# pour qu'un aller-retour de navigation ne recalcule pas tout.
|
||||
MEMORY_CACHE_BYTES = int(os.environ.get("LIDAR_TILE_MEMORY_CACHE_MB", "64")) * 1024 * 1024
|
||||
_mem_tiles = OrderedDict()
|
||||
_mem_tiles_bytes = [0]
|
||||
_mem_tiles_lock = threading.Lock()
|
||||
|
||||
|
||||
def _mem_get(key):
|
||||
with _mem_tiles_lock:
|
||||
data = _mem_tiles.get(key)
|
||||
if data is not None:
|
||||
_mem_tiles.move_to_end(key)
|
||||
return data
|
||||
|
||||
|
||||
def _mem_put(key, data):
|
||||
with _mem_tiles_lock:
|
||||
if key in _mem_tiles:
|
||||
return
|
||||
_mem_tiles[key] = data
|
||||
_mem_tiles_bytes[0] += len(data)
|
||||
while _mem_tiles_bytes[0] > MEMORY_CACHE_BYTES and _mem_tiles:
|
||||
_, old = _mem_tiles.popitem(last=False)
|
||||
_mem_tiles_bytes[0] -= len(old)
|
||||
|
||||
|
||||
def zoom_supported(z, scale=1):
|
||||
"""Vrai si le zoom demandé est dans la plage rendue par le serveur."""
|
||||
max_z = TILE_MAX_NATIVE_Z - (1 if scale == 2 else 0)
|
||||
@ -761,9 +803,10 @@ def get_tile(output_dir, layer, z, x, y, scale=1, fmt="png"):
|
||||
"""
|
||||
cache = tile_cache_path(output_dir, layer, z, x, y, scale, fmt)
|
||||
empty = cache.with_suffix(".empty")
|
||||
stored = zoom_cached(z, scale)
|
||||
sources = _contributing(output_dir, layer, z, x, y, scale)
|
||||
if not sources:
|
||||
if not empty.exists():
|
||||
if stored and not empty.exists():
|
||||
_write_atomic(empty, b"")
|
||||
return None
|
||||
|
||||
@ -772,6 +815,17 @@ def get_tile(output_dir, layer, z, x, y, scale=1, fmt="png"):
|
||||
m = src.mtime()
|
||||
if m and m > newest:
|
||||
newest = m
|
||||
if not stored:
|
||||
# Niveau non stocké : rendu à la volée, cache mémoire seulement.
|
||||
key = (str(output_dir), layer, z, x, y, scale, fmt, newest)
|
||||
data = _mem_get(key)
|
||||
if data is None:
|
||||
img = render_tile(output_dir, layer, z, x, y, scale)
|
||||
if img is None:
|
||||
return None
|
||||
data = _encode(img, fmt)
|
||||
_mem_put(key, data)
|
||||
return data
|
||||
try:
|
||||
if cache.stat().st_mtime >= newest:
|
||||
return cache.read_bytes()
|
||||
|
||||
Reference in New Issue
Block a user