Les guerres de cache se gagnent rarement sur des benchs et se perdent fréquemment en production à 2 h du matin, quand le graphe de stockage ressemble à un sismographe et que votre équipe base de données commence à dire « ça doit être le réseau ».
ZFS a l’ARC. Linux a le cache de pages. Les deux sont très bons dans ce qu’ils font, et les deux peuvent vous pourrir la journée si vous supposez qu’ils sont la même chose sous un autre nom.
Cet article porte sur la vérité pratique : ce que chaque cache stocke réellement, comment ils se comportent sous pression, pourquoi vous obtenez parfois un « double caching », et comment décider qui doit occuper la mémoire dans une charge mixte.
Vous aurez de l’histoire, des mécanismes, des récits d’incidents issus de schémas opérationnels réels, des commandes concrètes et un playbook de diagnostic rapide que vous pouvez utiliser avant que quelqu’un ne suggère « ajoutez juste de la RAM ».
Les deux caches, en une phrase
Le cache de pages Linux met en cache les données de fichiers telles que le noyau les voit via le VFS, de manière large et opportuniste ; l’ARC de ZFS met en cache les objets et métadonnées ZFS à l’intérieur de la pile ZFS, de façon agressive et selon ses propres règles.
En pratique : le cache de pages est le « cerveau » par défaut du système d’exploitation qui garde les choses à portée ; l’ARC est le cerveau de ZFS qui dit « je sais ce dont j’aurai besoin ensuite » — parfois plus malin, parfois têtu.
Blague #1 (rapide, pertinente) : demander « quel cache est meilleur » revient à demander si un chariot élévateur bat une camionnette. Si vous déplacez des palettes, le chariot vous impressionnera—jusqu’à ce que vous essayiez de le conduire sur l’autoroute.
Faits intéressants et courte histoire (qui compte vraiment)
Le caching n’est pas nouveau, mais les détails de où et comment il est implémenté façonnent les modes de défaillance opérationnels. Quelques points concrets qui influencent souvent les décisions :
- ZFS est né dans l’univers Solaris, où le système de fichiers et le gestionnaire de volumes étaient étroitement intégrés. L’ARC fait partie de ce design intégré, pas un cache « à la Linux » greffé dessus.
- L’ARC est adaptatif : il est conçu pour équilibrer le caching des données récemment utilisées et des données fréquemment utilisées (comportement MRU vs MFU approximatif). Cette adaptabilité est une fonctionnalité—et une source de surprises.
- ZFS contrôle l’intégrité avec checksum et peut s’auto-réparer grâce à la redondance. Cela signifie que les lectures ne sont pas seulement des « octets lus » ; il y a des métadonnées et une vérification qui peuvent être amplifiées ou atténuées par le caching.
- Le cache de pages Linux est plus ancien que beaucoup de systèmes de fichiers actuels. Il est profondément ancré dans les attentes de performance Linux ; de nombreuses applications en dépendent silencieusement même si elles n’en parlent pas.
- Historiquement, ZFS sur Linux a dû concilier deux gestionnaires de mémoire : la VM Linux et le comportement ARC de ZFS. Les versions modernes de ZoL/OpenZFS sont bien meilleures que les débuts, mais le modèle « deux cerveaux » reste important.
- L2ARC est arrivé plus tard quand les SSD sont devenus viables comme cache de lecture. Ce n’est pas « plus d’ARC » ; c’est une extension avec ses propres coûts, y compris la surcharge de métadonnées et le temps de chauffe.
- ZIL et SLOG concernent les écritures synchrones, pas le caching de lecture. Des gens achètent encore « un SLOG rapide » pour corriger la latence de lecture, ce qui revient à installer une meilleure boîte aux lettres pour améliorer l’acoustique du salon.
- Direct I/O et chemins de contournement ont évolué avec les bases de données. Beaucoup de moteurs DB sérieux apprennent à contourner délibérément le page cache ; ZFS a ses propres méthodes pour jouer dans cet espace, mais toutes les combinaisons ne sont pas heureuses.
- Linux moderne fonctionne avec des cgroups partout. Historiquement, ARC ne se comportait pas toujours comme un « bon citoyen » dans des limites mémoire ; les versions récentes ont amélioré cela, mais les équipes ops se font encore surprendre par des attentes divergentes.
Modèle mental : quoi vit où
Quand une application lit un fichier, imaginez un chemin en couches : app → libc → kernel VFS → système de fichiers → couche bloc → disque. Le cache de pages Linux se situe côté VFS et met en cache des pages de fichiers indexées par inode/offset de page.
ZFS, toutefois, a son propre pipeline : DMU (Data Management Unit) objets, dnodes, buffers ARC, ordonnanceur I/O vdev, et le pool. L’ARC met en cache au niveau ZFS, pas simplement des « pages de fichiers ».
Cette différence a trois conséquences opérationnelles :
- Métadonnées gagnent : les métadonnées ZFS (dnodes, blocs indirects, spacemaps) peuvent être mises en cache dans l’ARC, et le caching des métadonnées peut radicalement changer les performances de lectures aléatoires. Le cache de pages Linux met aussi en cache des métadonnées, mais les métadonnées ZFS sont… plus nombreuses.
- Compression/chiffrement changent l’économie : l’ARC peut conserver des buffers compressés selon les réglages ; le cache de pages tient généralement les pages de fichiers décompressées telles que les applications les voient.
- Les signaux d’éviction et de pression diffèrent : la VM Linux peut récupérer le cache de pages sous pression facilement. L’ARC peut se réduire, mais ses réglages et heuristiques peuvent être désalignés avec ce que le reste du système considère comme « pression ».
ZFS ARC deep dive (what it caches and why it’s weird)
Ce que l’ARC met réellement en cache
L’ARC n’est pas « un disque RAM pour vos fichiers ». Il met en cache des buffers ZFS : blocs de données et blocs de métadonnées tels qu’ils existent dans le pipeline ZFS. Cela inclut les données de fichiers, mais aussi l’échafaudage nécessaire pour trouver rapidement les données de fichiers :
structures dnode, pointeurs de blocs indirects, et plus.
En termes opérationnels, l’ARC explique pourquoi un pool ZFS qui semblait « en feu » pendant un scan riche en métadonnées se calme soudainement une fois chaud : la deuxième passe est principalement de la chasse de pointeurs en RAM plutôt que sur disque.
La politique adaptative de l’ARC (MRU/MFU) et pourquoi vous voyez des « misses » qui ne sont pas des échecs
L’ARC équilibre les buffers « récemment utilisés » et « fréquemment utilisés ». Il suit aussi des listes fantômes—des objets récemment évincés—pour apprendre s’il a pris la bonne décision. C’est astucieux et généralement utile.
Mais cela signifie que l’ARC peut sembler faire du travail même quand il « fonctionne comme prévu ».
Les opérateurs lisent souvent le taux de hit de l’ARC comme un KPI universel. Ce n’est pas le cas. Un faible taux de hit peut être correct si votre charge est du streaming de gros fichiers une seule fois. Un taux élevé peut être trompeur si vous mettez en cache par erreur une charge qui devrait être lue séquentiellement sans rétention.
Dimensionnement de l’ARC : la partie qui déclenche les discussions
Sous Linux, l’ARC concurrence tout le reste : cache de pages, mémoire anonyme, slab, et vos applications. L’ARC a des limites (zfs_arc_max et consorts), et il peut se réduire sous pression, mais le timing compte.
Quand la pression mémoire arrive vite (démarrage d’un job batch, gros tri, pics de conteneurs), l’ARC peut ne pas se réduire assez rapidement, et le noyau commencera à réclamer ailleurs—parfois le page cache, parfois des pages anonymes—provoquant des pics de latence ou même des OOM.
La question de réglage pratique n’est pas « quelle est la taille maximale de l’ARC ? » mais « quelle taille peut avoir l’ARC sans déstabiliser le reste de la machine ? »
ARC et comportement d’écriture : pas identique au page cache
Le cache de pages Linux est étroitement couplé au writeback et au comptage des pages dirty. ZFS a ses propres transaction groups (TXGs), des limites de données dirty, et un pipeline où les données sont mises en scène, écrites et engagées.
L’ARC lui-même concerne principalement les lectures, mais l’histoire mémoire système inclut les données dirty en vol et les mises à jour de métadonnées.
C’est pourquoi « mémoire libre » est la mauvaise métrique sur les systèmes ZFS. Ce qui compte, c’est la récupérabilité et la latence sous pression, pas si la machine semble vide dans un tableau de bord.
L2ARC : le cache SSD qui se comporte comme une seconde RAM lente
L2ARC étend l’ARC sur des dispositifs rapides, typiquement des SSD. Il peut aider les lectures aléatoires lorsque le working set dépasse la RAM et que le schéma d’accès présente de la réutilisation.
Mais ce n’est pas magique : L2ARC doit être peuplé (chauffe), il peut augmenter la pression mémoire à cause du suivi des métadonnées, et il ajoute une charge I/O sur le périphérique cache.
En production, la déception la plus courante avec L2ARC est d’attendre qu’il corrige une charge majoritairement constituée de lectures uniques. Vous ne pouvez pas cacher votre sortie d’un pétaoctet lu une seule fois.
Linux page cache deep dive (what it caches and why it’s everywhere)
Description du travail du page cache
Le cache de pages Linux met en cache des pages adossées à des fichiers : les octets exacts qui seraient retournés à un processus lisant un fichier (après la traduction du système de fichiers). Il met aussi en cache les métadonnées et les entrées de répertoire via les caches dentry et inode.
Sa puissance vient d’être le comportement par défaut : presque tous les systèmes de fichiers et presque toutes les applications en bénéficient automatiquement.
Récupération et writeback : le page cache est conçu pour être sacrifié
Linux traite le page cache comme récupérable. Sous pression mémoire, le noyau peut abandonner rapidement des pages de cache propres. Les pages dirty doivent être écrites, ce qui introduit de la latence et de l’I/O.
C’est pourquoi le réglage du « dirty ratio » peut changer les latences paliers dans les systèmes fortement en écriture.
Le page cache est un écosystème avec la VM : kswapd, reclaim direct, throttling des dirty, et comptabilité par cgroup (dans beaucoup de configurations). C’est pourquoi Linux semble souvent « auto-équilibré » comparé aux systèmes où les caches sont plus isolés.
Read-ahead et charges séquentielles
Le page cache est bon pour reconnaître les schémas d’accès séquentiels et effectuer du read-ahead. C’est un énorme avantage pour les lectures en streaming.
C’est aussi pourquoi votre benchmark qui lit un fichier deux fois paraît « incroyable » la seconde fois—à moins que vous ne contourniez le page cache ou que le fichier soit trop gros.
Direct I/O et moteurs de base de données
Beaucoup de bases de données utilisent direct I/O pour éviter le double buffering et contrôler leur propre cache. Cela peut avoir du sens quand le cache DB est mature et que le schéma d’accès est aléatoire.
Mais cela transfère aussi la charge de la justesse du caching et du tuning à l’application, ce qui est excellent jusqu’à ce que vous l’exécutiez dans une VM avec des voisins bruyants.
Alors qui gagne ?
La réponse honnête : aucune des deux ne « gagne » globalement. La réponse utile opérationnellement : l’ARC tend à l’emporter quand les métadonnées ZFS et l’intelligence au niveau ZFS dominent la performance, tandis que le page cache l’emporte quand la charge est orientée fichier, séquentielle, et s’aligne proprement sur le modèle VFS.
L’ARC « gagne » quand :
- Les métadonnées comptent : beaucoup de petits fichiers, snapshots, clones, traversées de répertoires, lectures aléatoires nécessitant des parcours profonds de l’arbre de blocs.
- Les fonctionnalités ZFS sont actives : compression, checksums, snapshots, réglage du recordsize—l’ARC met en cache les blocs « réels » et les métadonnées dans le format dont ZFS a besoin.
- Vous voulez que ZFS prenne les décisions : vous acceptez que le système de fichiers soit un participant actif, pas un simple magasin d’octets passif.
Le cache de pages Linux « gagne » quand :
- La charge est en streaming : grosses lectures séquentielles, pipelines média, lectures de sauvegarde, log shipping, gros scans ETL.
- Les applications attendent la sémantique de la VM Linux : beaucoup de logiciels sont réglés en supposant le reclaim du page cache et le comportement des cgroups.
- Vous n’utilisez pas ZFS : oui, évident, mais ça vaut la peine d’être dit—le page cache est la vedette par défaut pour ext4/xfs et consorts.
Le vrai match est « qui coopère mieux sous pression »
La plupart des incidents en production ne concernent pas la performance en régime permanent. Ils concernent ce qui se passe quand la charge change soudainement :
une réindexation démarre, une sauvegarde se lance, un conteneur se scale, un nœud commence à resilver, un job incontrôlé lit l’ensemble des données une fois.
Le « gagnant » est le système de cache qui se dégrade avec grâce face à ce changement. Sur Linux avec ZFS, cela signifie rendre l’ARC un bon citoyen pour que la VM du noyau n’ait pas à reclamper de façon panique dans le pire des scénarios.
Le piège du « double caching » (et quand c’est acceptable)
Si vous exécutez ZFS sur Linux et accédez aux fichiers normalement, vous pouvez vous retrouver avec du caching à plusieurs couches : l’ARC ZFS met en cache des blocs et des métadonnées ; le cache de pages Linux peut aussi mettre en cache des pages de fichiers selon la manière dont ZFS s’intègre au VFS.
Les détails dépendent de l’implémentation et de la configuration, mais la vérité opérationnelle est cohérente : vous pouvez dépenser la RAM deux fois pour mémoriser le même contenu.
Le double caching n’est pas toujours mauvais. Il peut être inoffensif si la RAM est abondante et que le working set est stable. Il peut être bénéfique si chaque cache conserve des « formes » de données différentes (métadonnées vs pages de fichiers) qui aident de manières distinctes.
Cela devient un problème quand la pression mémoire force des évictions et du reclaim dans une boucle de rétroaction : l’ARC s’accroche ; la VM récupère le page cache ; les applications font des fautes ; plus de lectures surviennent ; l’ARC grossit ; et la boucle recommence.
Blague #2 : le double caching, c’est comme imprimer deux fois le même rapport « au cas où ». Ça paraît prudent jusqu’à ce qu’il n’y ait plus de papier et que le CFO veuille le tableur budgétaire maintenant.
Trois mini-récits du monde de l’entreprise
Mini-récit n°1 : L’incident causé par une mauvaise hypothèse (« mémoire libre = tout va bien »)
Une équipe avec laquelle j’ai travaillé exploitait une plateforme analytique multi-tenant sur des nœuds Linux avec stockage ZFS. Les tableaux de bord étaient rassurants : l’utilisation mémoire semblait élevée mais stable, le swap était faible, et le service fonctionnait bien depuis des mois.
Puis un changement trimestriel de charge est arrivé : un client a commencé des scans plus larges sur des partitions anciennes, et un nouveau job batch a fait une énumération de fichiers agressive pour des rapports de conformité.
La latence a grimpé. Pas juste un peu—les latences aux extrémités sont passées de « personne ne se plaint » à « tickets de support toutes les cinq minutes ». La première réponse fut classique : « Mais on a de la RAM. Regardez, il reste de la mémoire libre. »
La deuxième réponse fut aussi classique : redémarrer un nœud. Ça allait mieux pendant une heure, puis ça replongea.
La mauvaise hypothèse était que la « mémoire libre » était l’indicateur principal, et que les caches céderaient poliment quand les applications auraient besoin de mémoire. En réalité, le système est entré en tempête de reclaim :
l’ARC occupait une grande part, le page cache a été récupéré agressivement, et la pression mémoire des applications a causé des fautes mineures fréquentes et des relectures. Pendant ce temps, ZFS faisait du vrai travail : parcours de métadonnées, vérification checksum, et I/O aléatoire qui faisait paraître les disques coupables.
La correction n’a pas été héroïque. Ils ont plafonné l’ARC pour laisser de la marge, surveillé les métriques de pression mémoire plutôt que la « free », et changé l’ordonnancement du job batch pour qu’il ne coïncide pas avec le pic interactif.
La véritable leçon : dans une charge mixte, « mémoire disponible » et « comportement de reclaim sous pression » comptent plus que la taille absolue de la RAM.
Mini-récit n°2 : L’optimisation qui s’est retournée contre eux (« ajoutons du L2ARC, ce sera plus rapide »)
Une autre organisation avait un pool ZFS sur de bons SSD mais voulait encore plus de performance de lecture pour un index de recherche. Quelqu’un a proposé d’ajouter un gros dispositif L2ARC parce que « plus de cache, c’est toujours mieux ».
Ils ont installé un grand NVMe comme L2ARC et ont vu les taux de hit monter dans la première journée. Tout le monde se sentait malin.
Une semaine plus tard, ils ont commencé à voir des pics de latence périodiques pendant les heures de pointe de requêtes. Rien ne saturait CPU. Le NVMe n’était pas à fond. Les disques du pool n’étaient pas saturés.
Les pics étaient étranges : courts, nets, et difficiles à corréler avec une métrique unique.
Le retour de flamme venait de deux endroits. D’abord, leur working set churnait : la charge de recherche avait des rafales de nouveaux termes et des opérations périodiques de re-rank complètes. L2ARC se peuplait de données qui ne seraient pas réutilisées.
Ensuite, le système payait une surcharge mémoire pour suivre et alimenter L2ARC, ce qui resserrait les marges mémoire. Sous pression, l’ARC et la VM du noyau ont commencé à se battre. Le symptôme n’était pas « lent tout le temps », mais « piques et imprévisible », ce qui est le pire pour des SLA d’entreprise.
Ils ont retiré L2ARC, augmenté la RAM à la place (ennuyeux mais efficace), et ont ajusté recordsize et compression pour l’index. Les performances se sont améliorées et, plus important, sont devenues prévisibles.
La leçon : L2ARC peut aider, mais ce n’est pas gratuit, et ça ne sauvera pas une charge à fort churn. Si votre périphérique de cache s’active à stocker des choses que vous ne redemanderez pas, vous avez construit un chauffage très cher.
Mini-récit n°3 : La pratique ennuyeuse mais correcte qui a sauvé la situation (« mesurer avant de tuner »)
Un service proche de la finance (batch de règlements, logs d’audit stricts) tournait sur ZFS avec un mélange de petits writes synchrones et de jobs périodiques de rapprochement orientés lecture.
Ils avaient une culture de gestion du changement que certains ingénieurs taquinaient en la qualifiant de « ralenti », mais elle avait une habitude que j’ai appris à apprécier : avant tout changement de performance, ils capturaient un bundle d’évidence standard.
Lorsqu’ils ont subi un ralentissement soudain après une mise à jour du noyau, ils n’ont pas commencé par tourner des manettes. Ils ont sorti leur bundle : stats ARC, pression VM, latence des périphériques bloc, état du pool ZFS, et métriques applicatives de haut niveau—mêmes commandes, mêmes fenêtres d’échantillonnage qu’avant.
En une heure, ils avaient quelque chose de rare en ops : un diff propre.
Le diff montrait que le dimensionnement ARC était inchangé, mais le comportement du page cache avait bougé : le timing du writeback dirty avait changé avec le nouveau noyau, ce qui interagissait avec leur pattern d’écriture sync et augmentait la latence d’écriture.
Parce qu’ils avaient des preuves de base, ils ont pu dire « c’est le comportement du writeback » plutôt que « le stockage est lent », et valider des corrections sans superstition.
La correction a été conservatrice : ajuster les paramètres dirty writeback dans des limites sûres et vérifier la santé du dispositif SLOG (il avait commencé à rapporter une latence intermittente).
Le service est resté stable, les auditeurs sont restés calmes, et personne n’a dû ouvrir une salle de crise pendant trois jours. La leçon : les rituels de mesure ennuyeux battent les suppositions de tuning excitantes.
Tâches pratiques : commandes et interprétation (au moins 12)
L’objectif de ces tâches n’est pas de « collecter des stats ». C’est de répondre à des questions spécifiques : l’ARC domine-t-il la mémoire ? Le page cache thrash-t-il ? Sommes-nous limité par la latence disque, le CPU ou le reclaim ?
Les commandes ci‑dessous supposent Linux avec OpenZFS installé là où c’est pertinent.
Task 1: See memory reality (not the myth of “free”)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 125Gi 42Gi 2.1Gi 1.2Gi 80Gi 78Gi
Swap: 8Gi 256Mi 7.8Gi
Interprétation : « available » est la ligne clé pour « combien d’espace les applis pourraient obtenir sans swap », mais c’est une simplification.
Un système peut afficher beaucoup de « available » et subir malgré tout des tempêtes de reclaim si la demande mémoire monte rapidement ou si de larges parties ne se récupèrent pas assez vite.
Task 2: Confirm ZFS ARC size, target, and limits
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c_min|c_max|c)\s'
size 4 68719476736
c 4 75161927680
c_min 4 17179869184
c_max 4 85899345920
Interprétation : size est la taille ARC actuelle. c est la cible ARC actuelle. c_min/c_max sont les bornes.
Si size colle à c_max pendant les périodes de forte activité et que la machine subit une pression mémoire, vous avez probablement besoin d’un plafonnement ou de plus de RAM—ou d’un changement de charge.
Task 3: Watch ARC behavior over time (misses vs hits)
cr0x@server:~$ arcstat 1 5
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
12:00:01 12K 2.4K 19 1.1K 9 1.0K 8 280 2 64G 70G
12:00:02 10K 2.0K 20 900 9 850 8 250 2 64G 70G
12:00:03 11K 2.2K 20 1.0K 9 950 9 260 2 64G 70G
12:00:04 13K 2.5K 19 1.2K 9 1.1K 8 290 2 64G 70G
12:00:05 12K 2.3K 19 1.1K 9 1.0K 8 270 2 64G 70G
Interprétation : Le pourcentage de misses seul n’est pas un verdict. Cherchez les changements : les misses ont-ils bondi au démarrage du job ? Les data misses sont-elles élevées (streaming) ou les metadata misses (parcours d’arbre) ?
Si arcsz est stable mais que les misses montent, votre working set peut dépasser l’ARC ou votre schéma d’accès présente peu de réutilisation.
Task 4: Identify memory pressure and reclaim storms (VM pressure)
cr0x@server:~$ cat /proc/pressure/memory
some avg10=0.12 avg60=0.20 avg300=0.18 total=9382321
full avg10=0.00 avg60=0.01 avg300=0.00 total=10231
Interprétation : PSI (Pressure Stall Information) vous dit si les tâches se bloquent parce que la mémoire ne peut pas être allouée rapidement.
Une montée de some suggère une activité de reclaim ; une montée de full signifie que le système est fréquemment incapable d’avancer — c’est là que la latence explose.
Task 5: Catch kswapd/direct reclaim symptoms quickly
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 262144 2200000 120000 78000000 0 0 120 900 3200 6400 12 6 78 4 0
3 1 262144 1900000 115000 77000000 0 0 220 2100 4100 9000 14 9 62 15 0
4 2 262144 1700000 112000 76000000 0 64 450 9800 5200 12000 18 12 44 26 0
2 1 262144 1600000 110000 75000000 0 0 300 6000 4700 10500 16 10 55 19 0
1 0 262144 2100000 118000 77000000 0 0 160 1400 3600 7200 13 7 76 4 0
Interprétation : Surveillez si/so (swap in/out), wa (I/O wait), et la colonne « b » (processus bloqués).
Une tempête de reclaim apparaît souvent par une augmentation de processus bloqués, un switch de contexte élevé, et un I/O erratique.
Task 6: See page cache, slab, and reclaimable memory
cr0x@server:~$ egrep 'MemAvailable|Cached:|Buffers:|SReclaimable:|Slab:' /proc/meminfo
MemAvailable: 81654312 kB
Buffers: 118432 kB
Cached: 79233412 kB
Slab: 3241120 kB
SReclaimable: 2015540 kB
Interprétation : Un grand Cached n’est pas intrinsèquement mauvais. Un grand Slab peut être normal aussi.
Mais si MemAvailable est faible pendant que l’ARC est élevé, vous risquez d’étrangler la VM. Si MemAvailable est OK mais que PSI est élevé, vous pourriez avoir de la fragmentation, des stalls de writeback, ou de la contention de cgroup.
Task 7: Check ZFS pool health and latent pain (scrub/resilver)
cr0x@server:~$ zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:11:34 with 0 errors on Tue Dec 24 03:14:11 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
errors: No known data errors
Interprétation : Un pool en resilver ou en scrub pendant le pic peut transformer une « discussion sur le cache » en « bagarre d’ordonnancement I/O ».
Vérifiez toujours cela en premier ; sinon vous réglerez l’ARC pendant que le pool fait l’équivalent moral de reconstruire un moteur en roulant.
Task 8: Measure disk latency at the block layer
cr0x@server:~$ iostat -x 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
13.22 0.00 7.11 18.90 0.00 60.77
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
sda 220.0 18432.0 2.0 0.90 9.20 83.78 70.0 9216.0 18.40 2.10 88.0
nvme0n1 1600.0 102400.0 120.0 6.98 0.40 64.00 800.0 51200.0 0.60 0.90 35.0
Interprétation : Un r_await/w_await élevé et un %util élevé suggèrent saturation du périphérique ou mise en file d’attente.
Si les disques semblent OK mais que la latence applicative est élevée, regardez la pression mémoire, le CPU, et la contention interne ZFS.
Task 9: Inspect ZFS dataset properties that change caching dynamics
cr0x@server:~$ zfs get -o name,property,value -s local,default recordsize,primarycache,secondarycache,compression tank/data
NAME PROPERTY VALUE
tank/data compression lz4
tank/data primarycache all
tank/data recordsize 128K
tank/data secondarycache all
Interprétation : recordsize façonne la granularité I/O et de caching pour les fichiers. Pour les bases de données, on veut souvent des records plus petits (par ex. 16K) pour réduire l’amplification de lecture.
primarycache contrôle ce qui va dans l’ARC (all, metadata, none). C’est un levier important.
Task 10: Cap ARC safely (persistent module option)
cr0x@server:~$ echo "options zfs zfs_arc_max=34359738368" | sudo tee /etc/modprobe.d/zfs-arc-max.conf
options zfs zfs_arc_max=34359738368
cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.0-xx-generic
Interprétation : Cela plafonne l’ARC à 32 GiB (valeur en octets). On fait ça quand la croissance de l’ARC menace la mémoire applicative ou provoque des tempêtes de reclaim.
Après reboot, confirmez via arcstats. Ne devinez pas ; vérifiez.
Task 11: Adjust primarycache to protect RAM from streaming reads
cr0x@server:~$ sudo zfs set primarycache=metadata tank/backups
cr0x@server:~$ zfs get -o name,property,value primarycache tank/backups
NAME PROPERTY VALUE
tank/backups primarycache metadata
Interprétation : Pour des cibles de sauvegarde qui sont principalement write-once/read-rarely ou en streaming, ne mettre en cache que les métadonnées empêche l’ARC d’être pollué par de grosses données à faible réutilisation.
Cette seule propriété a sauvé plus de boîtes à charge mixte que beaucoup de « guides de performance ».
Task 12: Observe ZFS I/O and latency inside the pool
cr0x@server:~$ zpool iostat -v 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 4.20T 3.05T 1.20K 650 140M 62.0M
raidz2-0 4.20T 3.05T 1.20K 650 140M 62.0M
sda - - 310 160 36.0M 15.0M
sdb - - 290 170 34.0M 15.5M
sdc - - 300 160 35.0M 15.0M
sdd - - 300 160 35.0M 15.0M
Interprétation : Cela vous donne une visibilité au niveau pool. Si les lectures sont élevées et que le taux de miss ARC est élevé, vous êtes probablement lié au disque.
Si les lectures sont élevées mais que les disques ne le sont pas, vous pourriez rebondir entre couches de cache ou être throttlé ailleurs.
Task 13: Spot dirty writeback and throttling (Linux VM)
cr0x@server:~$ sysctl vm.dirty_background_ratio vm.dirty_ratio vm.dirty_writeback_centisecs vm.dirty_expire_centisecs
vm.dirty_background_ratio = 10
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
Interprétation : Ces paramètres influencent quand le noyau commence le writeback en arrière-plan et quand il force les processus à écrire.
Sur les systèmes ZFS, vous jonglez aussi avec le comportement TXG de ZFS, donc les changements ici doivent être testés prudemment. Si vous voyez des pics périodiques de latence d’écriture, c’est un suspect.
Task 14: Validate whether a workload is streaming or reusing (cache usefulness test)
cr0x@server:~$ sudo perf stat -e minor-faults,major-faults,cache-misses -a -- sleep 10
Performance counter stats for 'system wide':
482,120 minor-faults
2,104 major-faults
21,884,110 cache-misses
10.002312911 seconds time elapsed
Interprétation : Les major faults indiquent des misses du page cache qui ont nécessité de l’I/O disque. Une hausse pendant un job suggère que le page cache n’aide pas (ou est récupéré).
Cela n’isole pas ARC vs cache de pages à lui seul, mais signale si le système amène des données en mémoire de façon répétée.
Playbook de diagnostic rapide
Quand la performance plonge et que tout le monde a une théorie, vous avez besoin d’une séquence courte qui converge rapidement. Voici l’ordre que j’utilise en incidents réels car il distingue « disque lent » de « mémoire qui se bat » en quelques minutes.
Step 1: Are we unhealthy or rebuilding?
Vérifiez l’état du pool et le travail de fond en premier. Si vous êtes en scrub/resilver, vous ne diagnostiquez pas un système propre.
cr0x@server:~$ zpool status
cr0x@server:~$ zpool iostat -v 1 5
Décidez : Si resilver/scrub est actif et que la latence est le problème, envisagez de replanifier ou de limiter avant de toucher aux réglages ARC/page cache.
Step 2: Is it disk latency or memory pressure?
cr0x@server:~$ iostat -x 1 5
cr0x@server:~$ cat /proc/pressure/memory
cr0x@server:~$ vmstat 1 5
Décidez :
Si les awaits disque sont élevés et l’utilisation est haute, vous êtes lié I/O. Si PSI mémoire est élevé et que le disque ne l’est pas, vous êtes lié à la mémoire/reclaim.
Si les deux sont élevés, vous pouvez avoir une boucle de rétroaction : reclaim cause I/O, qui cause des stalls, qui causent plus de reclaim.
Step 3: Is ARC oversized or misapplied?
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c|c_min|c_max|memory_throttle_count)\s'
cr0x@server:~$ arcstat 1 10
Décidez : Si l’ARC est près du max et qu’il y a pression mémoire, plafonnez l’ARC ou restreignez le caching sur les datasets en streaming (primarycache=metadata) pour arrêter la pollution du cache.
Step 4: Is the workload fundamentally cacheable?
cr0x@server:~$ arcstat 1 10
cr0x@server:~$ zpool iostat -v 1 10
Décidez : Si le taux de miss ARC reste élevé tandis que le débit est élevé et la réutilisation faible, arrêtez d’essayer de « gagner » avec des caches. Concentrez-vous sur le débit disque, le recordsize, et l’ordonnancement.
Step 5: Check dataset properties and application mismatch
cr0x@server:~$ zfs get -s local,default recordsize,atime,compression,primarycache tank/data
cr0x@server:~$ ps -eo pid,cmd,%mem --sort=-%mem | head
Décidez : Si une base de données est sur un dataset avec un recordsize énorme et le caching à « all », vous pourriez amplifier les lectures aléatoires et polluer l’ARC.
Corriger cela est souvent plus impactant que de micro-gérer les paramètres ARC.
Erreurs courantes, symptômes, corrections
Mistake 1: Treating ARC hit rate as the only truth
Synthômes : L’équipe fête un taux de hit à 95% tandis que les utilisateurs voient encore des pics de latence ; ou vous paniquez à 20% de hit sur un job de sauvegarde.
Correction : Classez la charge : streaming vs réutilisation. Mettez en paire arcstat avec la latence disque (iostat) et la pression mémoire (PSI). Un faible taux de hit sur des lectures streaming est normal ; une latence élevée ne l’est pas.
Mistake 2: Letting streaming workloads pollute ARC
Synthômes : Pendant les backups ou scans, l’ARC grossit, les charges interactives ralentissent, le cache paraît « inutile » après coup.
Correction : Mettez les datasets de streaming/sauvegarde en primarycache=metadata (ou même none pour les cas extrêmes). Envisagez des pools séparés si la contention est chronique.
Mistake 3: Capping ARC blindly and calling it “tuned”
Synthômes : Après réduction de l’ARC, les charges riches en métadonnées ralentissent drastiquement ; les disques deviennent plus occupés ; l’utilisation CPU monte.
Correction : Plafonnez l’ARC avec un objectif : laissez de la marge pour les applis et le page cache, mais pas si bas que ZFS perde son working set de métadonnées. Validez avec arcstat et la latence de bout en bout.
Mistake 4: Assuming L2ARC is a free lunch
Synthômes : L’ajout de L2ARC améliore les benchs synthétiques, mais la production devient piquante ; la pression mémoire augmente ; le périphérique cache est constamment actif.
Correction : Assurez-vous que la charge a de la réutilisation. Mesurez avant/après avec des percentiles de latence et des lectures disque. Si le churn domine, retirez L2ARC et dépensez le budget en RAM ou en meilleur stockage primaire.
Mistake 5: Confusing SLOG/ZIL with read caching
Synthômes : Vous achetez un SLOG rapide en espérant accélérer les lectures ; rien ne change ; vous décrétez ZFS « lent ».
Correction : Utilisez SLOG pour améliorer la latence des écritures synchrones où c’est approprié. Pour les lectures, concentrez-vous sur ARC/L2ARC, recordsize, et la latence des périphériques.
Mistake 6: Ignoring kernel memory pressure signals
Synthômes : Stalls périodiques, activité kswapd, OOM kills occasionnels, mais la « mémoire disponible » semble correcte.
Correction : Utilisez PSI (/proc/pressure/memory), vmstat, et les logs pour OOM/reclaim. Plafonnez l’ARC, corrigez les processus incontrôlés, et revoyez les limites mémoire des cgroups si des conteneurs sont impliqués.
Checklists / plan pas à pas
Checklist A: New ZFS-on-Linux host (mixed workloads)
-
Décidez votre budget mémoire. Combien de RAM doit être réservée pour les applications et combien peut être donné au caching système de fichiers ?
Si vous ne pouvez pas répondre, vous déléguez l’architecture aux heuristiques par défaut. -
Fixez un cap initial pour l’ARC (conservateur, ajustez ensuite). Vérifiez après reboot via
/proc/spl/kstat/zfs/arcstats. -
Classez les datasets par motif d’accès : interactif, base de données, sauvegarde/streaming, images VM. Réglez
primarycacheen conséquence. - Définissez le recordsize par dataset selon la charge (grand pour fichiers séquentiels, plus petit pour schémas DB aléatoires).
-
Établissez un bundle de base :
free,meminfo, PSI,arcstat,iostat -x,zpool iostat, et les percentiles de latence applicative.
Checklist B: When someone says “ZFS is eating all my RAM”
- Vérifiez PSI mémoire et l’activité swap. S’il n’y a pas de pression, l’ARC n’est pas le méchant—c’est votre RAM inutilisée qui fait du travail utile.
- Confirmez la taille ARC vs max et si l’ARC se réduit quand la charge change.
- Identifiez la charge polluante (souvent backups, scans, ou analytics). Appliquez
primarycache=metadataà ce dataset. - Si la pression persiste, plafonnez l’ARC. Puis validez que les charges critiques n’ont pas régressé à cause des misses de métadonnées.
Checklist C: Performance regression after a change
- Vérifiez la santé du pool, le statut de scrub/resilver, et les erreurs de périphériques.
- Comparez la latence disque (
iostat -x) avant/après. Si la latence a augmenté, n’argumentez pas encore sur les caches. - Comparez la pression mémoire (PSI) avant/après. Les changements du noyau peuvent déplacer le comportement de reclaim/writeback.
- Comparez le comportement ARC (taille, cible, misses). Si l’ARC est stable mais que l’app est plus lente, regardez plus haut (CPU, verrous, config app) ou plus bas (périphériques).
FAQ
1) Is ARC just “ZFS page cache”?
Non. L’ARC met en cache des buffers ZFS (données et métadonnées) à l’intérieur de la pile ZFS. Le cache de pages Linux met en cache des pages de fichiers au niveau VFS.
Ils peuvent se chevaucher, mais ce ne sont pas la même couche ni le même moteur de politique.
2) Why does Linux show “almost no free memory” on a healthy ZFS box?
Parce que la RAM est faite pour être utilisée. L’ARC et le page cache consomment la mémoire pour réduire les I/O futures.
La métrique qui compte est de savoir si le système peut satisfaire des allocations sans staller ou swapper—utilisez « available », PSI, et la latence observée.
3) Should I always cap ARC on Linux?
Sur des appliances de stockage dédiées, on laisse souvent l’ARC grand. Sur des serveurs à usage mixte (bases de données, conteneurs, JVM, agents de build), un plafonnement est généralement prudent.
Le bon cap dépend de la charge : laissez assez pour les applications et la VM, mais gardez assez d’ARC pour cacher les métadonnées et les blocs chauds.
4) Does adding more RAM always beat adding L2ARC?
Souvent, oui. La RAM réduit la latence et la complexité et aide à la fois l’ARC et le reste du système.
L2ARC peut aider quand le working set dépasse la RAM et a de la réutilisation, mais il ajoute une surcharge et ne réparera pas les charges à fort churn.
5) If my database uses direct I/O, does ARC still matter?
Ça peut. Même si les lectures des données utilisateur contournent certains chemins de cache, les métadonnées ZFS restent importantes, et ZFS gère toujours l’I/O bloc, les checksums et le layout.
De plus, tous les accès DB ne sont pas purement direct I/O tout le temps ; et des tâches d’arrière-plan peuvent toucher le système de fichiers de manière cacheable.
6) What’s the quickest way to tell if I’m I/O-bound or memory-pressure-bound?
Regardez iostat -x pour les await/%util des périphériques et PSI (/proc/pressure/memory) plus vmstat pour le reclaim/swap.
Un await disque élevé/%util suggère un lien I/O ; un PSI mémoire élevé suggère une pression de reclaim. Si les deux sont élevés, suspectez une boucle de rétroaction.
7) When should I set primarycache=metadata?
Quand le dataset sert principalement des lectures/écritures en streaming (sauvegardes, archives média, logs froids) et que mettre en cache les données de fichiers dans l’ARC écraserait des workloads plus chauds.
C’est particulièrement utile sur des systèmes multi-tenant où un job « lire tout une fois » peut évincer les blocs chauds des autres.
8) Why do my benchmarks look amazing after the first run?
Parce que les caches se sont chauffés. Ça peut être le page cache Linux, l’ARC, ou les deux. La seconde exécution mesure souvent la vitesse mémoire, pas le stockage.
Si vous essayez de mesurer le stockage, concevez le benchmark pour contrôler les effets de cache plutôt que de faire comme s’ils n’existaient pas.
9) Can I “drop caches” safely to test?
Vous pouvez vider le page cache Linux, mais le faire sur une machine de production est perturbant et généralement une mauvaise idée.
De plus, vider les caches Linux ne réinitialise pas forcément l’ARC de la même manière ; vous pouvez toujours mesurer un comportement ZFS chauffé. Préférez des hôtes de test contrôlés ou des charges synthétiques avec une méthodologie claire.
10) What’s the best single metric to monitor long-term?
Pour l’expérience utilisateur : les percentiles de latence au niveau applicatif. Pour la santé système : PSI mémoire et la latence disque.
Les stats ARC sont utiles comme preuves complémentaires, pas comme titre principal.
Conclusion
L’ARC de ZFS et le cache de pages Linux ne sont pas des concurrents au sens simpliste ; ce sont des systèmes de cache construits à différentes couches, avec des hypothèses et des modes de défaillance différents.
L’ARC est brillant pour mettre en cache le monde ZFS—blocs, métadonnées, et la machinerie qui rend snapshots et checksums rapides. Le cache de pages est l’amplificateur de performance par défaut du noyau Linux, conçu pour être récupérable et largement utile.
Ce qui doit vous préoccuper n’est pas une pureté idéologique (« ZFS devrait tout gérer » vs « Linux devrait tout gérer »), mais la stabilité opérationnelle face au changement.
Si vous exécutez des charges mixtes, laissez de la marge, empêchez la pollution du cache, mesurez la pression plutôt que la « mémoire libre », et affinez avec des preuves plutôt qu’avec des légendes.
C’est ainsi que vous gagnez la guerre des caches : en ne la transformant pas en combat.