# Reproduire le benchmark « librairies de cartes web »

Harnais, données brutes et procédure du benchmark publié dans l'article
[Benchmark des librairies de cartes web](https://learn.couble.eu/posts/2026-10-12-benchmark-librairies-cartes-web/).
Le contenu ci-dessous est identique à l'annexe de l'article.

## Contenu

| Chemin                      | Contenu                                                                |
| --------------------------- | ---------------------------------------------------------------------- |
| `protocol.md`               | Fiche de cadrage validée avant la campagne, avec journal des décisions |
| `harness/`                  | Code du benchmark (pages de test, serveur de rejeu, scripts), lockfile |
| `harness/FILES.txt`         | Liste des fichiers du harnais (pour le téléchargement)                 |
| `results/raw.csv`           | Toutes les mesures, une ligne par mesure, warm-up et échecs inclus     |
| `results/summary.csv`/`.md` | Statistiques produites par `analyze`                                   |
| `results/environment.json`  | Machine, OS, versions, dates de campagne                               |
| `charts/`                   | Graphiques SVG générés par `charts`                                    |

## Prérequis

- macOS sur Apple Silicon (campagne publiée : MacBook M2). Linux devrait
  fonctionner mais n'a pas été testé ; sous Linux, retirer
  `--use-angle=metal` dans `scripts/run.mjs` et vérifier que le rendu WebGL
  n'est pas logiciel (le script s'arrête s'il détecte SwiftShader).
- Node.js 24 et npm (campagne publiée : Node 24.21.0).
- `openssl` (présent par défaut sur macOS) pour le certificat du serveur de
  rejeu.
- Environ 600 Mo de disque (dépendances npm + Chromium de Playwright).
- Accès réseau uniquement pour les étapes d'installation et d'enregistrement ;
  les mesures elles-mêmes sont faites hors ligne, en rejeu.
- Aucune clé d'API, aucun service payant.

## Récupérer le harnais

Le dépôt du blog est privé : les fichiers sont téléchargeables depuis le site.

```bash
BASE=https://learn.couble.eu/benchmarks/2026-10-12-benchmark-librairies-cartes-web
mkdir -p bench-cartes && cd bench-cartes
curl -fsSL "$BASE/harness/FILES.txt" | while read -r f; do
  curl -fsSL --create-dirs -o "$f" "$BASE/harness/$f"
done
```

## Installer les dépendances

```bash
bash setup.sh   # curl ne conserve pas le bit d'exécution
```

`setup.sh` installe les dépendances épinglées (`npm ci`), le Chromium de
Playwright 1.64.0, génère un certificat auto-signé (`certs/`) et construit les
pages de test (`dist/`). Durée : 1 à 2 minutes selon la connexion.

## Constituer le cache de rejeu

Les mesures sont faites contre un serveur HTTP/2 local qui rejoue des réponses
enregistrées une fois. Les tuiles ne sont pas republiées ici ; il faut
reconstituer ce cache (`cache/`) :

```bash
# 1. Passe hors ligne : liste les tuiles raster que les pages demandent réellement (~4 min)
node scripts/run.mjs --discover --reps 1 --warmup 0
# 2. Téléchargement unique de ces tuiles (OSM + OpenSnowMap), séquentiel, 250 ms entre requêtes (~2 min)
npm run prefetch
# 3. Relancer 1 et 2 jusqu'à ce que la découverte annonce « 0 tuiles raster distinctes »
# 4. Génération des tuiles WebP (q=80) à partir des PNG
npm run webp
# 5. Enregistrement du style vectoriel ublo et des webfonts d'ol-mapbox-style (~1 min, deux fois)
npm run record-vector && npm run record-vector
```

L'étape 2 envoie environ 150 requêtes à `tile.openstreetmap.org` et autant à
`tiles.opensnowmap.org`. La
[tile usage policy d'OpenStreetMap](https://operations.osmfoundation.org/policies/tiles/)
interdit le téléchargement automatisé : la campagne publiée l'a fait une seule
fois, à petite échelle, en connaissance de cause. Ne la répétez pas en boucle.

Les tuiles OSM et OpenSnowMap évoluent : un cache reconstitué plus tard ne
contiendra pas exactement les mêmes octets que celui de la campagne publiée.

## Lancer le benchmark

```bash
npm run env                        # écrit results/environment.json
npm run run                        # 456 runs, ~46 min sur M2, résultats ajoutés à results/raw.csv
node scripts/capture-env.mjs --end # date de fin de campagne
```

Fermez les autres applications, branchez la machine sur secteur et ne vous
en servez pas pendant la campagne.

Options utiles de `scripts/run.mjs` :

| Option                              | Effet                                                |
| ----------------------------------- | ---------------------------------------------------- |
| `--reps N` / `--warmup N`           | répétitions mesurées / écartées (défaut 10 / 2)      |
| `--solutions leaflet-1,maplibre-gl` | sous-ensemble de solutions                           |
| `--tiles png,webp,vector,none`      | sous-ensemble de types de tuiles (`none` = baseline) |
| `--profiles mobile,desktop`         | sous-ensemble de profils                             |
| `--seed N`                          | graine de l'ordre entrelacé (défaut 20261012)        |
| `--out chemin.csv`                  | fichier de sortie (défaut `results/raw.csv`)         |

Run court pour vérifier l'installation (~4 min) :

```bash
node scripts/run.mjs --reps 1 --warmup 0 --out results/smoke.csv
```

## Analyser

```bash
npm run analyze                    # results/raw.csv → results/summary.csv + summary.md
node scripts/charts.mjs            # results/summary.csv → charts/*.svg
```

Pour analyser les résultats publiés, placez `raw.csv` dans `results/` puis
lancez `npm run analyze` : vous obtiendrez exactement les mêmes
`summary.csv` et `summary.md`.

Écarts attendus sur une autre machine : les **poids** (octets transférés)
dépendent du cache de rejeu et des libs, pas du matériel ; ils doivent être
très proches, à la variation près des tuiles OSM entre deux dates. Les
**temps** dépendent du processeur, du GPU et de la version de Chromium : seuls
les écarts relatifs entre solutions sont comparables.

## Dépannage

- **La campagne s'arrête sur « rendu WebGL logiciel détecté »** : Chromium
  n'a pas accès au GPU. Sur macOS, vérifier que les options
  `--use-angle=metal --enable-gpu` sont bien passées ; ailleurs, adapter
  `LAUNCH.args` dans `scripts/run.mjs`.
- **Timeouts sur les pages MapLibre en profil mobile** : presque toujours des
  tuiles absentes du cache (le serveur répond 404). Relancer la découverte et
  le téléchargement (étapes 1 à 3). La colonne `missing` de `raw.csv` compte
  ces absences par run.
- **Ports 8443 ou 8790 occupés** : le serveur de rejeu les utilise ; libérer
  ces ports.
