-wal et -shm à côté du DerivedData.
Pourquoi les checkpoints WAL ressemblent à des ralentissements CI « aléatoires »
Le write-ahead logging est souvent le bon défaut pour les outils développeur : les lecteurs chevauchent les écrivains, les commits s’appendent au fichier WAL, et la base reste cohérente si un processus tombe en pleine transaction. La douleur arrive quand les mêmes hôtes Mac mini M4 exécutent en parallèle des compilations, de larges tranches de tests et le dépaquetage de couches conteneur. Un checkpoint fusionne les pages WAL dans le fichier principal et déclenche une E/S riche en fsync ; sur un volume APFS déjà chargé — ou pire sur un partage réseau à métadonnées paresseuses — cette rafale se superpose au graphe de build et apparaît comme latence de queue dans les tableaux de bord CI, sans message d’erreur SQLite explicite.
- Sémantique du volume partagé : le WAL exige des verrous cohérents sur la base, les fichiers
-walet-shm. SMB et certaines piles NAS gèrent inégalement les verrous consultatifs et par plage ; « ça marchait sur mon portable » ne valide pas un pytest multi-hôtes. - Couplage jitter E/S : les builds concurrents randomisent déjà les files disque ; le checkpoint est périodique mais massif — ensemble ils produisent un jitter que la matrice Watchman vs Git, FSEvents et disque 1 To / 2 To traite comme signal de première classe.
- Pression disque masquée : les fichiers WAL grossissent pendant que les jauges d’utilisation restent « vertes » si vos alertes ignorent les fichiers satellites à côté des bases chaudes.
Si les artefacts quittent le nœud après build, alignez la politique rsync sur la matrice artefacts & rsync Mac mini M4 inter-régions pour que chemins de bases et exclusions de synchro restent homogènes entre régions.
WAL sur stockage partagé : ce qui doit être vrai avant de monter les écrivains
« Volume partagé » est un spectre. De l’APFS local sur chaque Mac mini M4 avec NFS réservé aux entrées plutôt lecture seule au dossier SMB unique où chaque worker ouvre le même build_state.db, l’écart est total. La documentation SQLite rappelle que les systèmes de fichiers réseau sont un choix de politique, pas une garantie : il faut des comportements de verrouillage que vous avez mesurés sous ouvertures parallèles depuis chaque région qui monte le partage.
- Pile validée : script de torture ouvrant la base depuis deux hôtes, transactions lecture/écriture mélangées et checkpoints forcés pendant qu’un faux job de compilation martèle des répertoires temporaires sur le même volume.
- Privilégier une voie d’écriture unique : même si le WAL est supporté, aligner le nombre d’écrivains sur le nombre de cœurs apporte surtout de la contention sur le WAL et le journal du système de fichiers.
- Plan B : répliquer vers un SSD local par worker (copier entrer, travailler, copier sortir) ou porter les métadonnées chaudes vers Postgres — gardez SQLite pour les caches de bord et les bacs à sable développeur lorsque la cohérence multi-hôte devient le goulot.
Pour les shells interactifs pendant ces exercices sur liaisons instables, croisez avec la matrice Mosh vs SSH, jitter et checklist flock afin de ne pas déboguer transport et stockage dans le même incident.
PRAGMA exécutables et journal_mode (préproduction d’abord)
Exécutez ces commandes sur un clone jetable des données de prod. L’ordre compte : fixez journal_mode avant les grosses écritures. synchronous=FULL est plus sûr sur un stockage douteux mais amplifie le coût des checkpoints ; NORMAL est le compromis CI habituel une fois la pile validée. Pour un partage NAS fragile, testez aussi PRAGMA journal_mode=DELETE; sur une copie : moins de fichiers satellites, mais amplification d’écriture sur le fichier principal — à n’utiliser qu’en attente d’une meilleure couche stockage.
-- Ouvrir la base, puis : PRAGMA journal_mode=WAL; -- droits en écriture ; peut reconstruire le journal PRAGMA synchronous=NORMAL; -- passer FULL si les fsync du stockage sont incertains PRAGMA temp_store=MEMORY; -- tables temporaires hors disque partagé si la RAM le permet PRAGMA busy_timeout=8000; -- ms ; temporiser plutôt qu’échouer tout de suite PRAGMA wal_autocheckpoint=1000; -- pages ; plus bas = checkpoints plus fréquents et plus petits -- Optionnel : borne cache (négatif = KiB) ; calibrer par RAM hôte, pas copier-coller aveugle PRAGMA cache_size=-64000; -- Inspection avant/après test de charge : PRAGMA journal_mode; PRAGMA page_count; PRAGMA wal_checkpoint(PASSIVE); -- TRUNCATE/RESTART seulement en fenêtre de maintenance
Si wal_autocheckpoint est trop agressif face aux rafales de build, l’exploitation voit des micro-blocages fréquents ; s’il est trop paresseux, le fichier WAL gonfle puis un checkpoint unique fige l’UI plusieurs secondes. Réglez selon la taille de page mesurée et le débit d’écriture, pas selon les défauts d’un dépôt modèle.
Évitez le réglage mmap_size sur fichiers servis par le réseau tant que le profilage page-in n’est pas fait ; un mmap large peut amplifier les tempêtes de lecture pendant les checkpoints.
Plafonds de concurrence file d’attente (un fichier, plusieurs workers)
Plafonds de départ conservateurs pour un fichier SQLite chaud sur stockage partagé servant les métadonnées CI (identifiants de build, index d’artefacts, historique de tests flaky). Re-benchmark après chaque upgrade majeur Xcode ou Swift : l’E/S du linker déplace le plafond.
| Modèle | Écrivains concurrents max | Lecteurs concurrents max | Note opérateur |
|---|---|---|---|
| SMB/NFS validé + WAL | 1 | 2 à 4 | Sérialiser les tâches écrivaines dans la file ; lecteurs seulement si les tests de torture passent. |
| Réplique APFS locale par hôte | 1 par fichier réplique | Lectures locales sans plafond dur | Fusionner via une seule étape de promotion sous verrou. |
| NAS inconnu / hérité | 0 partagé (DELETE ou base distante) | Ne pas monter les ouvertures parallèles | Risque de corruption silencieuse > commodité. |
La concurrence globale de l’orchestrateur peut rester élevée : seules les tâches qui touchent le même chemin de base subissent le plafond étroit. C’est la même philosophie que Nomad, affinité batch et verrous de build sur Mac mini M4, appliquée à la frontière données.
Verrous de build et checkpoints : garder la section critique minuscule
Un verrou de build autour de « publier l’arbre canonique » ne doit pas couvrir des tests longs — seulement le renommage atomique, la signature ou l’échange de manifeste. Des verrous longs étirent la croissance WAL : les écrivains s’accumulent derrière la barrière de promotion, puis les checkpoints rattrapent d’un coup à la libération. Reprenez la double couche du guide Nomad : sérialisation planificateur pour l’allocation « promote », plus flock sur un lockfile pour les scripts hors planificateur.
Réservez PRAGMA wal_checkpoint(RESTART) aux fenêtres calmes — jamais en parallèle d’une flotte de compilation complète, sauf si vous souhaitez des incidents fsync coordonnés.
Matrice décisionnelle : où doit vivre le fichier SQLite ?
Utilisez ce tableau lorsqu’une équipe plateforme propose « une seule base sur le partage pour toutes les régions ». Il complète les bandes d’utilisation disque que vous utilisez déjà pour planifier 1 To contre 2 To.
| Topologie | Recommandation WAL | Risque checkpoint / E/S | Cas d’usage |
|---|---|---|---|
| Base locale par nœud + rsync / fusion | WAL sur APFS | Faible ; checkpoints locaux. | Fort parallélisme de compilation ; cohérence éventuelle acceptable avec fusion explicite. |
| Copie « or » unique SMB/NFS | WAL seulement après tests de torture des verrous | Moyen à élevé ; couplé RTT réseau et latence de verrou. | Petite équipe, file d’écrivains unique stricte, exploitation NAS mature. |
| Multi-écrivains vers le même chemin | À éviter | Jitter sévère et risque d’intégrité. | Refonte : sharding, files d’écrivains ou serveur central. |
Checklist d’acceptation « seuils d’eau » 1 To / 2 To (WAL + CI)
Avant de valider un nouveau pool parallèle, parcourez cette liste avec stockage et propriétaires CI. Les pourcentages sont des bandes de départ — resserrez si instantanés APFS ou cibles Time Machine partagent le même conteneur.
- Hôtes 1 To : alerter lorsque l’empreinte projetée
.wal+.shm+ base dépasse environ 8 à 12 Go de façon soutenue pour le plus gros catalogue, ou lorsque l’utilisation du volume dépasse ~78 % sur plus d’un sprint — le premier seuil atteint déclenche une revue capacité. - Hôtes 2 To : marge WAL plus large mais bornez toujours les satellites : la latence de checkpoint dépend des octets WAL, pas seulement de l’espace libre. Traitez ~85 % d’utilisation comme « gel des nouvelles expériences risquées ».
- Cohabitation : mesurez la durée de checkpoint pendant un job de compilation représentatif ; le p95 ne doit pas dépasser le budget SLA du job.
- Sauvegardes : vérifiez que l’agent copie
-wal/-shmde façon atomique ou utilise l’API de sauvegarde en ligne de SQLite — une copie partielle corrompt la restauration. - Inter-régions : si la base est réellement partagée entre régions, ajoutez RTT et attentes de verrou au même tableau de bord que la latence DNS scindé et registre d’artefacts pour une lecture opérationnelle unifiée.
FAQ
Faut-il passer en journal_mode DELETE sur le partage ? Le mode DELETE réduit les fichiers satellites mais augmente l’amplification d’écriture sur le fichier principal pendant les transactions. C’est une atténuation transitoire raisonnable sur NAS capricieux ; la correction durable reste un meilleur stockage ou des répliques locales — pas une rotation permanente de modes.
Apple Silicon change-t-il le réglage SQLite ? La mémoire unifiée aide le cache de pages, mais le goulot reste NVMe et la contention réseau. Profilez sur de vrais hôtes Mac mini M4, pas sur des VM Intel.
Qui signe la checklist ? Plateforme SRE plus le mainteneur CI qui contrôle la profondeur de file ; la finance réutilise les mêmes signaux 1 To / 2 To pour caler les extensions disque avant que les incidents ne montent en comité de direction.
Comment lier cette matrice à Nomad ? Les plafonds de file d’attente ciblent le chemin de base ; les contraintes d’affinité et les verrous de promotion restent ceux de l’article Nomad affinité / flock — les deux couches se complètent.
journal_mode sur une copie des données de production. Les sémantiques de verrou varient selon le firmware NAS ; cet article ne remplace ni les matrices fournisseur ni les notes de version SQLite pour votre branche figée.
Ajouter des Mac mini M4 et garder une marge disque honnête
Comparez les forfaits, louez des nœuds via le parcours public achat sans mur de connexion forcée, et ouvrez le centre d’aide pour les schémas d’accès à côté de votre runbook — le paiement seulement lorsque l’équipe est prête.