Mesa llvmpipe vs SwiftShader: réduire le CPU Chromium de 49% sur Linux
Benchmark des backends GPU de Chromium sous Linux avec Xvfb. Passer de SwiftShader à Mesa llvmpipe via ANGLE GL réduit le CPU de 49% en conservant WebGL2, l'adaptateur WebGPU et le déterminisme du noise seed.
Vous voulez la documentation structurée pour Déploiement ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
Le benchmark en un tableau
Sur une charge de 25 secondes mêlant Canvas 2D et WebGL2 sous Xvfb, basculer le backend ANGLE de Chromium de SwiftShader à Mesa llvmpipe fait passer une instance d'environ 999% de CPU à 513%. C'est une réduction vérifiable de 49%, en conservant entièrement WebGL1 et WebGL2, en conservant le déterminisme de --bot-noise-seed à travers les empreintes canvas, WebGL1 et WebGL2, et en réduisant cinq flags GPU à deux. Pour les flottes Linux exécutant Chromium en headless pour des charges d'automatisation ou de protection des empreintes, c'est le gain de performance le moins coûteux disponible sans toucher au matériel ni à la concurrence des sessions.
| Backend | Flag ANGLE | WebGL2 | CPU moyen (deux passes) |
|---|---|---|---|
| A. SwiftShader | --use-angle=swiftshader --enable-unsafe-swiftshader | Oui | ~999% |
| B. Mesa llvmpipe (recommandé) | --use-angle=gl --bot-gpu-emulation=false | Oui | ~513% (-49%) |
| C. Mesa lavapipe | --use-angle=vulkan --enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLE | Non | ~153% (capacité cassée) |
La ligne lavapipe mérite un avertissement. Sur les paquets Mesa actuels distribués avec les distributions Linux courantes, Mesa lavapipe via ANGLE Vulkan laisse WebGL2 désactivé parce que certaines extensions Vulkan attendues par ANGLE pour la couverture complète de WebGL2 ne sont pas encore couvertes par l'ICD lavapipe. Le chiffre CPU paraît attractif mais la matrice des capacités s'effondre, donc l'option C n'est pas une option de production aujourd'hui.
Le reste de cet article explique ce que fait réellement chaque backend, pourquoi --disable-gpu casse silencieusement WebGL2 dans beaucoup de configurations, pourquoi SwiftShader est sur une voie de dépréciation que les équipes ops ne devraient pas ignorer, et comment une ligne de commande de deux flags remplace une pile de cinq flags escape-hatch tout en laissant intactes toutes les fonctionnalités de protection des empreintes.
Pourquoi SwiftShader consomme 999% de CPU sur les serveurs Linux headless
SwiftShader est un rasterizer CPU qui implémente OpenGL ES et Vulkan en logiciel. Il fait passer chaque shader, chaque fragment, chaque pixel par des instructions CPU, ce qui est exactement la raison de sa conception. Sur un serveur Linux sans GPU, SwiftShader donne à Chromium moderne un pipeline WebGL fonctionnel au prix d'une consommation CPU significative.
Le chiffre de 999% n'est pas une faute de frappe. Sur une charge de 25 secondes qui soutient les appels de dessin Canvas 2D et un fragment shader WebGL2 non trivial, dix cœurs CPU de pcpu est ce qu'il faut à SwiftShader pour garder la boucle de rendu au rythme attendu par Chromium. Multipliez cela par le nombre d'instances Chromium concurrentes sur un host typique de flotte et le coût devient la ligne dominante du budget CPU.
Il y a une seconde raison, plus discrète, qui compte. Les versions récentes de Chromium ont placé SwiftShader derrière un flag explicite --enable-unsafe-swiftshader. Le nommage est intentionnel. L'amont signale que le chemin SwiftShader n'est plus le fallback par défaut et peut être supprimé entièrement dans une release future. Continuer à dimensionner la capacité autour du coût CPU de SwiftShader coûte à une flotte Linux maintenant et crée un risque de migration plus tard.
La raison plus profonde pour laquelle llvmpipe gagne sur le même matériel se trouve dans le modèle d'exécution. SwiftShader interprète les opérations de shader via des helpers C++ portables et parallélise sur un pool de threads, mais chaque fragment passe encore par du code CPU générique. Mesa llvmpipe prend le code source du shader, le compile une fois en JIT via LLVM en code machine natif, et émet des instructions SIMD vectorisées qui exécutent plusieurs pixels par cycle sur chaque cœur CPU. Le diagramme ci-dessous résume la différence.
Les options de backend GPU pour Chromium sous Linux
Trois backends de rendu logiciel sont distribués avec ou autour du Chromium actuel sous Linux. Ils diffèrent par l'API, par le chemin de code à travers ANGLE et par la surface des capacités. Le diagramme ci-dessous trace le chemin d'appel depuis un launch Playwright ou Puppeteer jusqu'au rasterizer qui fait le vrai travail sur les pixels.
En clair: l'application lance Chromium, Chromium passe les appels WebGL à ANGLE, et ANGLE choisit l'un des trois rasterizers logiciels en fonction du flag --use-angle=. Chaque rasterizer a un profil coût-capacité différent. Le chemin recommandé éclaire la boîte verte: Mesa llvmpipe via ANGLE GL, la moitié du CPU de SwiftShader, capacité WebGL2 entièrement préservée.
A. SwiftShader via ANGLE est le fallback historique. Il est autonome, ne nécessite aucun paquet Mesa système, et fait du rendu sur CPU avec des pools de threads. C'est aussi le chemin que Chromium est en train d'abandonner, comme expliqué dans la section dépréciation plus bas.
B. Mesa llvmpipe via ANGLE GL est le chemin que cet article recommande. ANGLE cible la pile OpenGL système via --use-angle=gl, la pile OpenGL système sur un serveur sans GPU se résout vers libgl1-mesa-dri, et libgl1-mesa-dri charge llvmpipe. llvmpipe est un rasterizer LLVM JIT multi-threadé qui est plus efficace sur les CPU modernes que SwiftShader et qui est officiellement supporté par Mesa comme fallback de rendu logiciel. Crucial: la pile OpenGL logicielle de Mesa est suffisamment mature pour exposer des surfaces WebGL1 et WebGL2 complètes via ANGLE.
C. Mesa lavapipe via ANGLE Vulkan est l'option la plus récente. ANGLE cible Vulkan via --use-angle=vulkan, l'ICD Vulkan sur un serveur sans GPU se résout vers lavapipe, et lavapipe est l'implémentation Vulkan logicielle de Mesa. La consommation CPU pure est la plus basse des trois pour le rendu brut, mais le backend WebGL2 d'ANGLE sur Vulkan a besoin d'un ensemble d'extensions Vulkan que le lavapipe upstream actuel ne couvre pas entièrement, ce qui laisse WebGL2 désactivé. Cela peut changer à mesure que Mesa mûrit.
Pourquoi --disable-gpu désactive silencieusement WebGL2
Beaucoup de tutoriels Linux Chromium attrapent --disable-gpu comme solution en une ligne pour les problèmes de rendu sur serveur headless. Sur Chromium moderne, ce flag a des effets en cascade que les opérateurs auditent rarement avant que quelque chose ne casse.
Une ligne de commande avec --disable-gpu nu sur un serveur Linux aujourd'hui produit cet état:
| Capacité | Statut avec --disable-gpu nu |
|---|---|
navigator.gpu présent | Oui |
navigator.gpu.requestAdapter() retourne adapter | null |
canvas.getContext('webgl') | échoue |
canvas.getContext('webgl2') | échoue |
Canvas 2D fonctionne encore, mais toutes les surfaces WebGL ont disparu. Les charges de protection des empreintes qui dépendent du hashing WebGL, les flux d'automatisation qui sondent requestAdapter pour la détection des capacités, et tout scénario moderne de vérification publicitaire qui touche WebGL2 vont échouer de manières subtiles.
La raison pour laquelle beaucoup de déploiements en production ne voient pas ce mode de défaillance est qu'ils ont empilé manuellement quatre flags escape-hatch par-dessus --disable-gpu:
--disable-gpu
--enable-unsafe-swiftshader # un-deprecates the SwiftShader path
--enable-unsafe-webgpu # un-deprecates the software WebGPU path
--use-gl=angle # forces ANGLE wiring
--ignore-gpu-blocklist # skips the Chromium GPU blocklist
Cette pile fonctionne dans le sens où WebGL1, WebGL2 et requestAdapter reviennent. Elle verrouille aussi le déploiement sur le chemin SwiftShader déprécié et sur quatre flags dont les noms contiennent les mots unsafe ou ignore. Chaque mise à niveau de Chromium est un coup de dés sur le retrait éventuel de l'un de ces flags.
La sortie la plus propre de cette pile consiste à supprimer --disable-gpu, supprimer les quatre flags escape-hatch, et remplacer le groupe entier par deux flags qui routent Chromium directement à travers Mesa llvmpipe. C'est exactement ce que fait la configuration recommandée plus bas.
Benchmarking Mesa llvmpipe vs SwiftShader sous Xvfb Chromium
Le benchmark qui a produit le chiffre de 49% utilisait Xvfb comme display virtuel. Sur les serveurs Linux sans display physique, Xvfb est la façon standard d'exécuter Chromium en mode headed. Le chemin du compositor en mode headed atteint l'écran via ANGLE, ce qui rend visible le choix du backend ANGLE dans la consommation CPU. C'est la forme de déploiement recommandée pour la protection des empreintes et le rendu cohérent sur les flottes Linux.
La configuration Xvfb headed est aussi le déploiement qui expose le plus de gain potentiel d'un changement de backend. Le diagramme ci-dessous oppose les deux pipelines.
La charge consistait en 25 secondes de rendu soutenu: une simulation de particules Canvas 2D sur la moitié gauche d'une viewport de 1280 par 800, plus un fragment shader WebGL2 rendant un bruit rotatif sur la moitié droite. La consommation CPU a été échantillonnée avec ps -o pcpu= -p <chromium tree> sommé sur tous les processus Chromium pour ce profil unique, moyennée sur deux passages complets pour contrôler la charge transitoire de l'hôte.
La colonne Mesa llvmpipe est celle que les flottes Linux Chromium en production devraient cibler. Elle économise du CPU par rapport à SwiftShader d'un facteur d'environ 1.95, préserve la surface WebGL complète, et repose sur la pile OpenGL logicielle que Mesa maintient officiellement.
Pourquoi Mesa lavapipe n'est pas encore une option de production
Le chiffre de 153% CPU pour lavapipe est réel, et c'est aussi un piège. La sonde de capacités sous cette configuration rapporte navigator.gpu.requestAdapter() retournant null et que getContext('webgl') et getContext('webgl2') échouent tous deux à allouer.
La cause se situe côté ANGLE. Le backend WebGL d'ANGLE sur Vulkan exige un ensemble cohérent d'extensions Vulkan et de feature flags avant d'exposer WebGL2. Les drivers Vulkan matériels couvrent généralement cet ensemble. Mesa lavapipe, en tant qu'implémentation Vulkan logicielle, ne couvre pas encore chaque extension qu'ANGLE recherche. ANGLE détecte les pièces manquantes et désactive entièrement la surface WebGL2 plutôt que d'exposer une version dégradée. Les versions plus récentes de Mesa rétrécissent cet écart, mais les distributions Linux sur des canaux de release stables sont en retard.
À l'intérieur d'environnements containerisés, l'écart s'élargit. L'isolation du conteneur rend la découverte de l'ICD Vulkan moins stable, ce qui explique en partie pourquoi la ligne lavapipe s'effondre à adapter=null même quand l'hôte hors conteneur aurait produit un adapter fonctionnel. Pour les déploiements en conteneur la conclusion est la même: choisir Mesa llvmpipe via ANGLE GL, pas lavapipe via ANGLE Vulkan.
Cela vaut la peine d'être revisité plus tard. Au fur et à mesure que la couverture de Mesa lavapipe se rapproche des drivers Vulkan principaux, l'avantage CPU de la barre de droite devient accessible sans perdre WebGL2. Pour l'instant, llvmpipe est la seule option qui combine basse CPU et capacité complète.
Router WebGL2 de Chromium à travers Mesa llvmpipe
Les deux flags qui routent un serveur Linux Chromium à travers Mesa llvmpipe avec capacité WebGL2 complète sont:
--use-angle=gl
--bot-gpu-emulation=false
--use-angle=gl indique à ANGLE de cibler la pile OpenGL système. Sur un serveur Linux avec libgl1-mesa-dri, libglx-mesa0, libegl-mesa0 et libvulkan1 installés, la pile OpenGL système se résout vers Mesa, et Mesa sans GPU réel se résout vers llvmpipe. ANGLE mappe alors les appels WebGL1 et WebGL2 sur des appels OpenGL, llvmpipe les rasterize, et le résultat est livré à la page.
--bot-gpu-emulation=false désactive la couche BotBrowser qui synthétise les lectures de GPU buffer au-dessus d'ANGLE. Sur un vrai rasterizer CPU comme Mesa llvmpipe, cette couche est redondante: ANGLE plus llvmpipe produisent déjà une sortie de pixels stable et déterministe pour les surfaces WebGL, et les hashes rendus restent cohérents sous la même --bot-noise-seed. Désactiver la synthèse évite le travail en double.
Crucialement, --bot-gpu-emulation=false ne désactive aucune des autres couches de protection des empreintes. Le bruit Canvas 2D, les chaînes spoofées UNMASKED_VENDOR_WEBGL et UNMASKED_RENDERER_WEBGL fournies par le profil, la propagation de --bot-noise-seed sur toutes les surfaces de hashing, et toutes les autres propriétés d'identité restent en vigueur. La portée du flag est volontairement étroite.
SwiftShader est en cours de dépréciation, --enable-unsafe-swiftshader est un pansement
--enable-unsafe-swiftshader est un signal upstream clair. Le flag existe parce que SwiftShader n'est plus quelque chose que Chromium veut activer par défaut. Le préfixe "unsafe" est le marqueur de dépréciation upstream. Les opérateurs qui s'appuient aujourd'hui sur le chemin SwiftShader tournent sur du temps emprunté, et la fenêtre d'emprunt est fixée par le calendrier de release upstream plutôt que par la roadmap du déploiement.
Une chronologie de migration pratique ressemble à ceci:
| Phase | Statut de SwiftShader | Action requise |
|---|---|---|
| Aujourd'hui | Disponible derrière --enable-unsafe-swiftshader | Migrer quand cela convient |
| Court terme | Le flag reste, les warnings augmentent | Migrer avant la prochaine mise à niveau majeure |
| Éventuellement | Flag retiré ou chemin supprimé | Migration obligatoire |
Mesa llvmpipe se trouve sur une courbe différente. C'est le backend OpenGL logiciel officiel que le projet Mesa maintient. Pas de flag de dépréciation, pas de préfixe "unsafe", pas de message upstream sur le retrait. Les opérateurs choisissant llvmpipe aujourd'hui choisissent le chemin que Mesa et Chromium prévoient de supporter indéfiniment.
Matrice des capacités à travers les configurations
La surface complète des capacités à travers les configurations décrites ci-dessus est présentée ci-dessous. Cinq lignes sont évaluées contre quatre vérifications de capacité: présence de navigator.gpu, requestAdapter retournant un adapter non nul, getContext('webgl') allouant un contexte WebGL1, et getContext('webgl2') allouant un contexte WebGL2.
| Configuration | navigator.gpu | requestAdapter | WebGL1 | WebGL2 |
|---|---|---|---|---|
--disable-gpu nu | oui | null | échec | échec |
--disable-gpu --use-angle=gl (conflit de flags) | oui | null | échec | échec |
| Pile escape-hatch de cinq flags (SwiftShader effectif) | oui | oui | oui | oui |
Mesa llvmpipe via --use-angle=gl --bot-gpu-emulation=false | oui | oui | oui | oui |
Mesa lavapipe via --use-angle=vulkan ... | oui | null | échec | échec |
Les deux lignes qui apparaissent toutes vertes sont la pile escape-hatch SwiftShader et la recette à deux flags Mesa llvmpipe. Les deux livrent une capacité complète. Seule la ligne Mesa llvmpipe livre aussi l'économie de 49% CPU et la propriété de compatibilité ascendante.
Vérifier le déterminisme du rendu sous --bot-noise-seed
Une couche de protection des empreintes respectueuse de la vie privée doit faire deux choses à la fois. Elle doit varier la sortie rendue à travers les identités pour que des profils différents produisent des empreintes différentes. Et elle doit garder cette sortie stable pour une identité donnée à travers les passages, pour que le même profil reproduise la même empreinte au re-test.
--bot-noise-seed est le flag BotBrowser qui pilote cela. La même seed doit produire les mêmes hashes canvas, WebGL1 et WebGL2 à chaque run. Des seeds différentes doivent produire des hashes différents sur chaque surface. Le chemin Mesa llvmpipe a été sondé avec les seeds 100, 100 (re-run), 200 et 300 pour vérifier les deux propriétés.
| Seed | Hash Canvas 2D | Hash WebGL1 | Hash WebGL2 |
|---|---|---|---|
| 100 (run 1) | 9c18bdc53952 | 0f9829ee244b | b879347569e8 |
| 100 (run 2) | 9c18bdc53952 | 0f9829ee244b | b879347569e8 |
| 200 | 5c41b9d30fbf | 7742375e5a30 | 58f6f468d8da |
| 300 | 676363d51dae | 248aee43160d | 86925e9b41ac |
Six vérifications passent sur cette matrice: les hashes seed 100 sont identiques sur les deux runs sur les trois surfaces (trois vérifications de reproductibilité), les hashes seed 100 et seed 200 diffèrent sur les trois surfaces (trois vérifications de divergence), les hashes seed 200 et seed 300 diffèrent sur les trois surfaces (trois vérifications de divergence supplémentaires). Avec les quatre vérifications de capacité ci-dessus, la configuration Mesa llvmpipe produit un résultat de vérification 10 sur 10.
Configuration recommandée pour les flottes Linux Chromium headless
La configuration minimale qui livre la capacité complète, l'économie de 49% CPU, et la compatibilité ascendante ressemble à ceci en ligne de commande:
# Installer les paquets Mesa de rendu logiciel
sudo apt-get install -y \
libgl1-mesa-dri \
libglx-mesa0 \
libegl-mesa0 \
libvulkan1
# Lancer Chromium avec deux flags GPU
chromium-browser \
--bot-profile=/path/to/profile.enc \
--use-angle=gl \
--bot-gpu-emulation=false \
--no-sandbox \
--user-data-dir="$(mktemp -d)"
Exécuter cela sous Xvfb sur un serveur sans display est direct:
Xvfb :99 -screen 0 1280x800x24 &
export DISPLAY=:99
chromium-browser --use-angle=gl --bot-gpu-emulation=false ...
Les flags qui doivent être retirés des déploiements existants avant d'ajouter les deux nouveaux sont listés ci-dessous. Plusieurs entreront en conflit avec --use-angle=gl s'ils sont laissés en place, et n'importe lequel d'entre eux annulera silencieusement la migration.
| Flag à retirer | Pourquoi |
|---|---|
--disable-gpu | Cascade vers adapter null et échec WebGL, en plus du conflit avec --use-angle=gl |
--enable-unsafe-swiftshader | Force le chemin SwiftShader déprécié |
--use-gl=swiftshader | Identique, déprécié |
--use-gl=angle | Vieille syntaxe, remplacée par --use-angle=gl |
--enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLE | Bascule ANGLE vers lavapipe et désactive WebGL2 |
--use-angle=vulkan | Identique |
--ignore-gpu-blocklist | Significatif uniquement avec la pile SwiftShader, redondant sur Mesa |
Pour les launches Playwright et Puppeteer, les mêmes flags entrent directement dans la liste args:
// Playwright
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser',
args: [
'--use-angle=gl',
'--bot-gpu-emulation=false',
'--bot-profile=/path/to/profile.enc',
'--no-sandbox',
],
});
// Puppeteer
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser',
args: [
'--use-angle=gl',
'--bot-gpu-emulation=false',
'--bot-profile=/path/to/profile.enc',
'--no-sandbox',
],
});
Arbre de décision: choisir un backend GPU pour votre charge Linux
Un arbre de décision court capture la recommandation pratique pour les trois scénarios de flotte Linux Chromium les plus courants.
Votre charge a-t-elle besoin de la capacité WebGL1 ou WebGL2?
│
├── Oui (cas commun pour la protection des empreintes,
│ la vérification publicitaire, le rendu web moderne)
│ │
│ └── Utilisez Mesa llvmpipe via ANGLE GL.
│ Deux flags: --use-angle=gl --bot-gpu-emulation=false
│ 49% d'économie CPU vs SwiftShader, WebGL1 et WebGL2 complets.
│
├── Non, la charge est purement DOM et Canvas 2D
│ │
│ └── Mesa llvmpipe reste recommandé pour la compatibilité future.
│ Mêmes deux flags. Les surfaces WebGL restent disponibles
│ même si la charge ne les utilise pas actuellement.
│
└── Vous ne pouvez pas changer les flags maintenant (gel de déploiement legacy)
│
└── Gardez la pile escape-hatch SwiftShader à court terme.
Planifiez la migration avant la prochaine mise à niveau majeure de Chromium.
Ajoutez un rappel calendrier pour revisiter quand cette release sera distribuée.
Pour la plupart des flottes en production, la réponse est la première branche. La recette à deux flags Mesa llvmpipe livre l'économie CPU, la parité de capacité et la compatibilité ascendante. Aucun scénario ne justifie de garder SwiftShader comme défaut à long terme, étant donné le signal de dépréciation upstream.
Mettre la configuration en production
Les étapes de migration pour une flotte typique ressemblent à ceci:
- Installer les paquets Mesa sur chaque host de la flotte:
libgl1-mesa-dri,libglx-mesa0,libegl-mesa0,libvulkan1. - Mettre à jour la commande de launch pour une instance canary, en remplaçant la pile de flags GPU par
--use-angle=gl --bot-gpu-emulation=false. - Exécuter la suite d'automatisation standard contre le canary. Confirmer que les contextes WebGL1 et WebGL2 s'allouent, que
navigator.gpu.requestAdapter()retourne un adapter non nul, et que toute page de vérification se rend avec le contenu attendu. - Échantillonner la consommation CPU contre la baseline existante. L'instance Mesa llvmpipe devrait s'asseoir à environ la moitié du CPU de l'instance SwiftShader sous charge équivalente.
- Re-exécuter les vérifications de hash déterministes sous
--bot-noise-seed: même seed reproduit les mêmes hashes, seeds différentes produisent des hashes différents, sur canvas, WebGL1 et WebGL2. - Roll forward au reste de la flotte.
La référence complète pour ces flags, y compris les interactions GeoIP et proxy sur Linux, se trouve dans le guide de déploiement Linux GPU backend et le guide de configuration de serveur headless. Pour le modèle de protection des empreintes plus large dans lequel --bot-gpu-emulation et --bot-noise-seed participent, l'aperçu du fingerprinting navigateur couvre la carte des surfaces complète.
Conclusion
Le choix du backend GPU Linux Chromium est une décision à fort levier qui se prend souvent par accident. SwiftShader est le chemin sur lequel la plupart des flottes atterrissent par défaut, et c'est le chemin qui coûte le plus de CPU et duquel l'amont s'éloigne. Mesa llvmpipe via ANGLE GL est le chemin qui livre une réduction de 49% CPU sous Xvfb, préserve toutes les capacités WebGL et adapter WebGPU que la pile applicative attend, préserve le déterminisme --bot-noise-seed à travers les hashes canvas, WebGL1 et WebGL2, et remplace une pile escape-hatch de cinq flags par une ligne de commande à deux flags. Les flottes Linux exécutant BotBrowser pour la protection des empreintes ou les charges d'automatisation devraient être sur ce chemin aujourd'hui.
Articles Connexes
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.