Volver al Centro de conocimiento
Despliegue

Mesa llvmpipe vs SwiftShader para Chromium en Linux

Elige entre Mesa llvmpipe con ANGLE GL y SwiftShader para Chromium en Linux: un 49% menos de CPU en una ejecución headed, CPU similar en headless y dos flags.

BotBrowser Team

Documentación

Quieres la documentación estructurada de Despliegue?

Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.

Un servidor Linux sin GPU sigue necesitando un rasterizador por software para que Chromium tenga WebGL operativo. A través de ANGLE hay dos opciones prácticas: SwiftShader y Mesa llvmpipe, a la que se llega mediante el backend OpenGL de ANGLE. En la medición de BotBrowser, una sesión headed sobre una pantalla virtual (Xvfb) ejecutó unos 25 segundos de dibujo con Canvas 2D más un shader WebGL2. SwiftShader usó aproximadamente 999% de CPU para esa carga y Mesa llvmpipe aproximadamente 513%. Eso es cerca de un 49% menos de CPU, con WebGL1, WebGL2 y el adaptador WebGPU disponibles en ambos casos.

TL;DR

  • En la medición headed sobre Xvfb, SwiftShader usó cerca de 999% de CPU y Mesa llvmpipe cerca de 513%, alrededor de 49% menos, con WebGL1, WebGL2 y el adaptador WebGPU todavía disponibles.
  • En el modo headless por defecto los dos backends usaron cerca de 713.5% y 713.3%, así que allí la migración aporta estabilidad de capacidades y no CPU.
  • La ruta llvmpipe son dos flags, --use-angle=gl --bot-gpu-emulation=false, tras instalar libgl1-mesa-dri, libglx-mesa0, libegl-mesa0 y libvulkan1.
  • --disable-gpu a secas hace que requestAdapter() devuelva null y rompe getContext('webgl') y getContext('webgl2'), y tiene prioridad sobre --use-angle=gl si ambos están presentes.
  • La fila de lavapipe con unos 153% pierde WebGL2 y el adaptador WebGPU en Ubuntu 22.04, así que su menor CPU no es comparable.

Contenido

Qué muestra la medición

Chromium envía las llamadas WebGL por ANGLE a SwiftShader, Mesa llvmpipe o Mesa lavapipe, con CPU de unos 999%, 513% y 153% en una ejecución headed

El resultado tiene un límite claro. Procede de una sola carga headed sobre pantalla virtual, en un host Ubuntu 22.04 x86_64 con un perfil de Windows 11, sumando la CPU de ps en todos los procesos de Chromium y promediando dos ejecuciones. No describe todas las cargas ni todos los hosts. En el modo headless por defecto, los dos backends consumen casi la misma CPU.

ModoBackendCPU mediaQué significa
Headed sobre XvfbSwiftShader~999%Referencia
Headed sobre XvfbMesa llvmpipe~513%Cerca de un 49% menos que la referencia
Headed sobre XvfbMesa lavapipe~153%WebGL2 desactivado, no sirve en producción
Headless por defectoSwiftShader con el conjunto completo de flags unsafe~713.5%Referencia
Headless por defectoMesa llvmpipe~713.3%CPU casi igual, pico de memoria unos 100 MB mayor

La fila de lavapipe es una advertencia, no una recomendación. Su CPU baja procede de una configuración que pierde WebGL2 y el adaptador WebGPU, así que el ahorro no es comparable con las otras dos filas.

Lee la tabla según el modo que uses. Si alguna parte de tu pipeline es headed, como una pantalla virtual para capturas, comprobaciones manuales o la ruta headless antigua, la ganancia de CPU es real. Si ya usas el modo headless por defecto, no esperes ahorro de CPU. El motivo para migrar ahí es tener WebGL, WebGL2 y WebGPU estables sin depender de flags --enable-unsafe-*. Para saber qué comparar entre sesiones headless y headed, consulta Consistencia de perfiles entre navegadores headless y headed, que explica cómo registrar el par compatible y clasificar las diferencias.

La misma lectura, organizada por tipo de despliegue, queda así:

Tipo de despliegueExpectativa de CPUMotivo para migrar
Sesión headed sobre pantalla virtualMenor con llvmpipe, en el rango medido aquíAhorro de CPU y un conjunto de flags más pequeño
Ruta headless antigua o pipelines de capturas que corren headedMenor con llvmpipe, verifícalo con tu propia cargaAhorro de CPU y compatibilidad futura
Modo headless por defectoCasi igual que SwiftShaderWebGL y WebGPU estables sin flags unsafe
Despliegue congelado por ahoraSin cambios hasta que migresPlanifica el cambio antes de la próxima actualización mayor de Chromium

Por qué SwiftShader cuesta más aquí y en qué se diferencian los tres backends

SwiftShader es un rasterizador por CPU que implementa OpenGL ES y Vulkan en software. Cada invocación de shader se ejecuta en núcleos de CPU, que es para lo que fue creado. Es autocontenido y no necesita paquetes de Mesa del sistema, por eso es el camino en el que acaban muchas flotas Linux por defecto.

Una lectura de 999% significa que unos diez núcleos de CPU estuvieron ocupados mientras corría la carga. Multiplícalo por el número de instancias de un host y el backend de renderizado pasa a ser una parte grande del presupuesto de CPU. La medición muestra la diferencia entre los backends, pero no aísla por qué uno es más barato que otro, así que no afirma nada sobre su funcionamiento interno.

Mesa documenta llvmpipe como un rasterizador por software que usa LLVM para generar código en tiempo de ejecución y que corre en varios hilos sobre los núcleos de CPU. En un servidor sin GPU física, Mesa lo selecciona automáticamente cuando ANGLE apunta a la pila OpenGL del sistema.

ANGLE es la capa que Chromium usa para traducir las llamadas WebGL a una API gráfica nativa, y el flag --use-angle elige a qué API apunta. Esa elección decide qué rasterizador por software hace el trabajo. Existen tres caminos:

  • SwiftShader mediante ANGLE es la opción de respaldo histórica. Chromium reciente la mantiene detrás de --enable-unsafe-swiftshader, y la palabra unsafe en ese nombre es la señal de upstream de que el camino ya no es el predeterminado.
  • Mesa llvmpipe mediante ANGLE GL usa --use-angle=gl. ANGLE habla con la libGL del sistema y Mesa la enlaza con llvmpipe cuando no hay GPU física. Los puntos de entrada WebGL1, WebGL2 y WebGPU siguen disponibles, y ningún flag de la configuración lleva la etiqueta unsafe.
  • Mesa lavapipe mediante ANGLE Vulkan es el rasterizador Vulkan por software. Necesita extensiones Vulkan que ANGLE espera para WebGL2, y no todas las versiones de Mesa las incluyen.
BackendFlags necesariosAdaptador WebGPUWebGL1WebGL2Compatible a futuro
Mesa llvmpipe (recomendado)--use-angle=gl --bot-gpu-emulation=falsesísísísí
SwiftShader--disable-gpu --enable-unsafe-swiftshader --use-gl=angle --ignore-gpu-blocklistsísísíobsoleto y protegido por unsafe
Mesa lavapipe, bare metal, Ubuntu 22.04--use-angle=vulkan --enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLEno (null)sínosí en Ubuntu 24.04 y posteriores
Mesa lavapipe, Docker, cualquier distribuciónigual que arribano (null)nonono viable para producción
--disable-gpu a secassolo --disable-gpuno (null)nonoutilizable solo con flags adicionales

navigator.gpu como propiedad está presente en todas las filas. La columna de WebGPU indica si navigator.gpu.requestAdapter() devuelve un adaptador utilizable. Para ver cómo se expone el adaptador y qué revela, consulta Huella digital WebGPU: la próxima generación de rastreo por GPU, que cubre los detalles del adaptador y cómo controlarlos.

Conviene mirar lavapipe de cerca porque su cifra de CPU resulta tentadora. En Ubuntu 22.04, el Mesa 23.2 empaquetado no incluye todas las extensiones Vulkan que ANGLE necesita para WebGL2. WebGL1 sigue funcionando en bare metal, pero WebGL2 falla y el adaptador WebGPU es null. Dentro de Docker, la carga del ICD de Vulkan también es frágil, así que lavapipe muchas veces ni arranca y WebGL1 deja de funcionar también. Ubuntu 24.04 con Mesa 24.2 o posterior mejora el caso bare metal, mientras que el comportamiento en contenedores sigue siendo poco fiable hoy. Vuelve a revisar lavapipe cuando tus hosts usen un Mesa más reciente, y hasta entonces considéralo aún no apto para producción en la configuración probada.

Los proyectos upstream describen su propio papel con claridad. El README de ANGLE presenta a ANGLE como la capa que traduce llamadas de OpenGL ES a otros backends gráficos, como Vulkan y OpenGL de escritorio, y por eso un solo valor de --use-angle basta para mover Chromium entre los tres rasterizadores. El repositorio de SwiftShader describe una implementación de la API gráfica Vulkan basada en CPU que aporta independencia del hardware. La documentación de Mesa describe llvmpipe como parte de los drivers de software Gallium que Mesa mantiene. En conjunto explican por qué llvmpipe es una ruta de software soportada y no una vía de escape.

El flag de SwiftShader es también una cuestión de calendario. Chromium ha marcado el camino como protegido por unsafe, lo que sugiere que quizá no siga disponible, pero no hay una fecha pública de retirada. Los pipelines que dependen de él perderán WebGL si algún día se retira el flag, así que migrar pronto convierte un corte forzado en un cambio planificado.

Por qué --disable-gpu a secas elimina los adaptadores WebGL y WebGPU

Muchos tutoriales de Chromium en Linux sugieren --disable-gpu como arreglo de una línea para problemas de renderizado en servidores. En el Chromium actual, ese flag por sí solo desactiva el descubrimiento de adaptadores WebGPU y los dos contextos WebGL. navigator.gpu sigue presente, pero requestAdapter() devuelve null, y tanto getContext('webgl') como getContext('webgl2') fallan. Canvas 2D sigue funcionando, por eso el problema suele pasar desapercibido hasta que una página necesita WebGL.

Muchos despliegues de producción evitan ese fallo porque apilan flags de escape sobre --disable-gpu:

--disable-gpu
--enable-unsafe-swiftshader
--enable-unsafe-webgpu
--use-gl=angle
--ignore-gpu-blocklist

Cada flag de esa pila tiene una función distinta. --enable-unsafe-swiftshader mantiene disponible el camino de SwiftShader, --enable-unsafe-webgpu mantiene disponible el camino WebGPU por software, --use-gl=angle fuerza la conexión con ANGLE y --ignore-gpu-blocklist omite la lista de bloqueo de GPU de Chromium. Ninguno hace falta en el camino de llvmpipe.

Esta pila de cinco flags funciona en el sentido de que WebGL1, WebGL2 y el adaptador vuelven a aparecer. También ata el despliegue al camino de SwiftShader y a cuatro flags cuyos nombres contienen unsafe o ignore. Así, cada actualización de Chromium trae la duda de si alguno de esos flags ha cambiado de comportamiento.

Hay una trampa más. --disable-gpu tiene prioridad sobre --use-angle=gl tanto en modo headed como en headless. Si añades el flag de Mesa y dejas --disable-gpu, llvmpipe nunca entra en efecto y la configuración parece indicar que la migración no hizo nada.

La salida más limpia es eliminar --disable-gpu y los cuatro flags de escape, y sustituir todo el grupo por los dos flags de la sección siguiente. Quien sepa nombrar la pila de cinco flags, la pila de dos flags y el motivo por el que --disable-gpu a secas elimina el descubrimiento de adaptadores ya ha entendido toda la migración.

La configuración de llvmpipe con dos flags

Primero instala los paquetes de Mesa en espacio de usuario que permiten a ANGLE llegar a llvmpipe:

sudo apt-get update
sudo apt-get install -y \
    libgl1-mesa-dri \
    libglx-mesa0 \
    libegl-mesa0 \
    libvulkan1

Después lanza con los dos flags. En el modo headless por defecto no hace falta pantalla:

chromium-browser \
    --headless \
    --no-sandbox \
    --user-data-dir="$(mktemp -d)" \
    --bot-profile="path/to/profile.enc" \
    --use-angle=gl \
    --bot-gpu-emulation=false

Para una sesión headed sobre pantalla virtual, quita --headless y proporciona una pantalla:

DISPLAY=:10.0 chromium-browser \
    --no-sandbox \
    --user-data-dir="$(mktemp -d)" \
    --bot-profile="path/to/profile.enc" \
    --use-angle=gl \
    --bot-gpu-emulation=false

--use-angle=gl dirige ANGLE por la pila OpenGL del sistema, y Mesa carga llvmpipe cuando no hay GPU física. --bot-gpu-emulation=false indica a BotBrowser que deje que el driver GL real dibuje la salida WebGL mientras el ruido de Canvas 2D y la capa de variación de --bot-noise-seed siguen activos. El flag es estrecho a propósito: no desactiva el perfil ni el resto de la protección de fingerprint.

--bot-gpu-emulation acepta tres valores. false es el ajuste de esta migración. true es el modo estándar por defecto. priority añade una planificación priorizada de la GPU para cargas con muchos contextos concurrentes en una instancia del navegador, funciona de forma independiente de la elección del backend GL y no hace falta cuando false entrega el trabajo de GPU al driver real.

Cuando migres un despliegue existente, elimina estos flags antes de añadir los dos nuevos. Varios entran en conflicto con --use-angle=gl, y cualquiera de ellos puede deshacer el cambio sin mostrar ningún error.

Flag a eliminarMotivo
--disable-gpuDesactiva el descubrimiento de adaptadores y los dos contextos WebGL, y prevalece sobre --use-angle=gl
--enable-unsafe-swiftshaderSolo hace falta para mantener vivo SwiftShader
--use-gl=swiftshaderActivación explícita de SwiftShader, superada por llvmpipe
--use-gl=angleForma antigua sustituida por --use-angle=gl y puede entrar en conflicto con ella
--ignore-gpu-blocklistNo hace falta, porque llvmpipe no está en la lista de bloqueo
--enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLEFija el camino de lavapipe, que desactiva WebGL2 en bare metal con Ubuntu 22.04
--use-angle=vulkanFuerza el mismo camino de lavapipe
--disable-vulkan-surfaceSolo es relevante para el camino Vulkan

Dentro de un contenedor, añade los mismos cuatro paquetes de Mesa a la imagen y pasa los mismos dos flags al lanzar. Ejecutar el contenedor con --shm-size=2g da a Chromium más memoria compartida y mejora la estabilidad. Recuerda que lavapipe es el backend que falla en contenedores, así que un despliegue en contenedores es un motivo más para quedarse en llvmpipe mediante ANGLE GL.

Conserva --headless, --no-sandbox si ya lo usabas, todos los flags --bot-* incluidos --bot-profile y --bot-noise-seed, y tu configuración de red y de --user-data-dir. En lanzamientos con Playwright o Puppeteer, los mismos flags van en la lista args:

const browser = await chromium.launch({
  executablePath: 'path/to/botbrowser',
  args: ['--use-angle=gl', '--bot-gpu-emulation=false', '--bot-profile=path/to/profile.enc'],
});

Diferencias de salida entre rasterizadores y reproducibilidad con semilla

Distintos rasterizadores por software producen una salida de píxeles distinta para el mismo shader. Después de pasar de SwiftShader a Mesa llvmpipe, los bytes exactos de readPixels o toDataURL serán diferentes. Es el comportamiento esperado de dos rasterizadores distintos, no una señal de que la migración haya fallado.

Los campos que una página lee como identidad siguen bajo control del perfil. User-Agent, plataforma y las cadenas de proveedor y renderizador sin enmascarar vienen de tu perfil y no cambian con el backend. El comportamiento de --bot-noise-seed tampoco cambia: la misma semilla reproduce la misma salida dentro del backend elegido, y una semilla distinta produce una salida distinta y estable.

De ahí salen dos reglas prácticas. Mantén capturas de referencia por backend en lugar de comparar bytes entre SwiftShader y llvmpipe. Y cuando compares antes y después de una migración, compara ejecuciones del mismo backend y con la misma semilla, para que una regresión real no quede oculta tras una diferencia esperada entre rasterizadores.

Despliegue con un host canario en una flota Linux

Valida el cambio en un host canario antes de tocar el resto de la flota. La secuencia siguiente mantiene cada paso observable:

  1. Instala libgl1-mesa-dri, libglx-mesa0, libegl-mesa0 y libvulkan1 en el host canario.
  2. Sustituye la pila de flags de GPU por --use-angle=gl --bot-gpu-emulation=false en una instancia y reiníciala, porque los cambios de flags solo se leen al arrancar.
  3. Confirma que los contextos WebGL1 y WebGL2 se crean y que navigator.gpu.requestAdapter() devuelve un adaptador no null.
  4. Abre chrome://gpu y comprueba que las filas de WebGL, WebGL2 y WebGPU indican renderizado por software mediante ANGLE y OpenGL en lugar de desactivado. La misma página muestra la cadena activa de ANGLE y del driver, lo que confirma que se usa llvmpipe.
  5. Mide la CPU frente a una referencia de SwiftShader equivalente, en el mismo modo headed o headless y con la misma carga.
  6. Repite las comprobaciones con la misma semilla y con una semilla distinta, y después extiende el cambio al resto de la flota.

La tabla siguiente relaciona los síntomas más frecuentes con su causa habitual.

SíntomaCausa habitualSolución
Adaptador null y fallan los dos contextos WebGL--disable-gpu a secas, o lavapipe dentro de DockerElimina --disable-gpu y los flags de Vulkan, deja solo los dos flags
WebGL1 funciona, WebGL2 y adaptador nulllavapipe en bare metal con un Mesa antiguoElimina los flags de Vulkan y cambia a --use-angle=gl
libGL error: failed to load driver: swrastFaltan los paquetes de Mesa en espacio de usuarioInstala libgl1-mesa-dri, libglx-mesa0 y libegl-mesa0
chrome://gpu sigue mostrando SwiftShaderUn flag lo fuerza de nuevo, como --use-gl=swiftshaderElimina el flag y reinicia el proceso
La CPU no bajóModo headless por defecto, donde domina la cargaEs lo esperado, el valor ahí es la estabilidad y la compatibilidad futura
Cambió la salida de píxeles WebGLRasterizador distintoEs lo esperado, reconstruye la captura de referencia para el nuevo backend

Una comparación equivalente es lo que hace fiable la cifra de CPU. Usa el mismo host, el mismo perfil, la misma carga y el mismo modo para ambos backends. Ejecuta una carga lo bastante larga como para mantener ocupado el renderizado, por ejemplo unos 25 segundos de dibujo con Canvas 2D junto con un shader WebGL2. Suma la CPU de todos los procesos de Chromium de la instancia, repite la prueba al menos dos veces y promedia las ejecuciones para que un pico breve de carga del host no decida el resultado. Un ahorro medido en un modo no dice nada del otro modo, así que lanza la referencia en el modo que vayas a usar. Para saber cómo revisar la salida de Canvas, WebGL y WebGPU entre backends, consulta Validación de privacidad en distintos backends de renderizado, que cubre una matriz de renderizado y un orden de pruebas controlado.

Prevé el caso en que la CPU no se mueva. En el modo headless por defecto, el renderizado va a un búfer fuera de pantalla sea cual sea el backend activo, así que el trabajo de Canvas y WebGL domina y los dos backends cuestan casi lo mismo. Aun así, la migración compensa ahí como estabilidad de capacidades y un conjunto de flags más pequeño que no depende de flags unsafe.

BotBrowser documenta una ruta de backend GPU en Linux en la que --use-angle=gl con --bot-gpu-emulation=false permite que Mesa llvmpipe dibuje WebGL mientras el ruido de Canvas 2D y la reproducibilidad de --bot-noise-seed siguen activos, de modo que puedes validar la migración de dos flags en un host canario antes de cambiar el resto de la flota. BotBrowser no puede hacer que Mesa llvmpipe sea más rápido de lo que permite el host, no garantiza ahorro de CPU en el modo headless por defecto, no puede mantener idénticos los bytes de píxeles WebGL entre rasterizadores y no controla el calendario de upstream de Chromium para retirar SwiftShader. El flag --bot-gpu-emulation requiere ENT Tier 2.

Para la preparación básica del host, lee la guía de configuración de servidores headless y la guía de despliegue con Docker. Para el comportamiento de la semilla entre backends, lee reproducibilidad de la semilla de ruido. La referencia completa de flags está en la guía de despliegue del backend GPU en Linux.

Fuentes públicas

Conclusión práctica

Quita --disable-gpu y los cuatro flags de escape, instala los cuatro paquetes de Mesa y arranca con --use-angle=gl --bot-gpu-emulation=false en un host canario antes de tocar la flota. Después repite la misma carga de unos 25 segundos en el modo que realmente publicas, porque un ahorro headed de cerca del 49% no dice nada del headless por defecto, y mantén la comparación de semilla en dos sesiones para que las diferencias de salida entre rasterizadores sigan visibles.

#Chromium#Linux#Gpu#Mesa#Swiftshader#Webgl#rendimiento#Benchmark#headless#Xvfb

Este artículo forma parte de la guía: Despliegue y versión del navegador: mapa operativo

Lleva BotBrowser de la investigación a producción

Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.