Назад в Центр знаний
Развертывание

Mesa llvmpipe и SwiftShader для Chromium в Linux

Выберите Mesa llvmpipe через ANGLE GL или SwiftShader для Chromium в Linux: примерно на 49% меньше CPU в режиме headed, одинаковый CPU в headless и настройка из двух флагов.

BotBrowser Team

Документация

Нужна структурированная документация по теме Развертывание?

Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.

Linux-серверу без GPU по-прежнему нужен программный растеризатор, чтобы Chromium поддерживал рабочий WebGL. Через ANGLE есть два практичных варианта: SwiftShader и Mesa llvmpipe, доступный через OpenGL-бэкенд ANGLE. В измерении BotBrowser сессия headed на виртуальном дисплее (Xvfb) выполняла около 25 секунд рисования Canvas 2D вместе с шейдером WebGL2. SwiftShader использовал примерно 999% CPU, а Mesa llvmpipe примерно 513%. Это около 49% экономии CPU, при этом WebGL1, WebGL2 и адаптер WebGPU остаются доступными.

TL;DR

  • В измерении headed на Xvfb SwiftShader занял около 999% CPU, а Mesa llvmpipe около 513%, то есть примерно на 49% меньше, при этом WebGL1, WebGL2 и адаптер WebGPU остались доступны.
  • В режиме headless по умолчанию оба бэкенда показали около 713.5% и 713.3%, поэтому там переход даёт стабильность возможностей, а не экономию CPU.
  • Путь llvmpipe это два флага, --use-angle=gl --bot-gpu-emulation=false, после установки libgl1-mesa-dri, libglx-mesa0, libegl-mesa0 и libvulkan1.
  • Чистый --disable-gpu заставляет requestAdapter() вернуть null и ломает getContext('webgl') и getContext('webgl2'), а при наличии обоих флагов он перекрывает --use-angle=gl.
  • Строка lavapipe с примерно 153% теряет WebGL2 и адаптер WebGPU на Ubuntu 22.04, поэтому её низкий CPU не поддаётся сравнению.

Содержание

Что показывает измерение

Chromium передаёт вызовы WebGL через ANGLE в SwiftShader, Mesa llvmpipe или Mesa lavapipe; в режиме headed CPU составляет около 999%, 513% и 153%

У результата есть чёткая граница. Это одна нагрузка headed на виртуальном дисплее, запущенная на хосте Ubuntu 22.04 x86_64 с профилем Windows 11; CPU суммировался через ps по всем процессам Chromium, а среднее взято из двух запусков. Результат не описывает любую нагрузку или любой хост. В стандартном режиме headless оба бэкенда используют почти одинаковый CPU.

РежимБэкендСредний CPUЧто это означает
Headed на XvfbSwiftShader~999%Базовый уровень
Headed на XvfbMesa llvmpipe~513%Примерно на 49% ниже базового уровня
Headed на XvfbMesa lavapipe~153%WebGL2 отключён, для production не подходит
Стандартный headlessSwiftShader с полным набором флагов unsafe~713.5%Базовый уровень
Стандартный headlessMesa llvmpipe~713.3%CPU примерно такой же, пик памяти примерно на 100 MB выше

Строка lavapipe: это предупреждение, а не рекомендация. Низкое значение CPU получено в конфигурации, которая теряет WebGL2 и адаптер WebGPU, поэтому такую экономию нельзя сравнивать с двумя другими строками.

Читайте таблицу с учётом используемого режима. Если часть вашего конвейера работает headed, например виртуальный дисплей для скриншотов, ручных проверок или старого headless-пути, выигрыш CPU реален. Если вы уже используете стандартный headless, не ожидайте снижения CPU. В этом случае миграция нужна ради стабильной доступности WebGL, WebGL2 и WebGPU без флагов --enable-unsafe-*. О том, что сравнивать между headless- и headed-сессиями, см. Согласованность профиля в headless и headed браузере: там описано, как фиксировать поддерживаемую пару и классифицировать различия.

Та же информация по форме развёртывания:

Форма развёртыванияОжидание по CPUЗачем мигрировать
Headed-сессия на виртуальном дисплееНиже с llvmpipe, в пределах измеренного диапазонаЭкономия CPU и меньшее число флагов
Старый headless-путь или headed-конвейер скриншотовНиже с llvmpipe, проверьте на своей нагрузкеЭкономия CPU и совместимость в будущем
Стандартный headlessПримерно как у SwiftShaderСтабильные WebGL и WebGPU без unsafe-флагов
Развёртывание пока замороженоБез изменений до миграцииЗапланируйте переход до следующего major-релиза Chromium

Почему SwiftShader здесь дороже и чем отличаются три бэкенда

SwiftShader: программный растеризатор на CPU, реализующий OpenGL ES и Vulkan. Каждый вызов шейдера выполняется на ядрах CPU, для этого он и создан. Он автономен и не требует системных пакетов Mesa, поэтому многие Linux-флоты используют его по умолчанию.

Показатель 999% означает, что во время нагрузки были заняты примерно десять ядер CPU. Умножьте это на число экземпляров на хосте, и бэкенд рендеринга станет значительной частью бюджета CPU. Измерение показывает разницу между бэкендами, но не отделяет причину, по которой один дешевле другого, поэтому не делает заявлений об их внутреннем устройстве.

Mesa описывает llvmpipe как программный растеризатор, использующий LLVM для генерации кода во время выполнения и работающий в несколько потоков на ядрах CPU. На сервере без аппаратного GPU Mesa выбирает его автоматически, когда ANGLE нацелен на системный стек OpenGL.

ANGLE: слой, через который Chromium переводит вызовы WebGL в нативный графический API; флаг --use-angle выбирает целевой API. От этого выбора зависит, какой программный растеризатор выполняет работу. Возможны три пути:

  • SwiftShader через ANGLE: исторический резервный путь. Современный Chromium оставляет его за --enable-unsafe-swiftshader, и слово unsafe в названии показывает, что этот путь больше не является стандартным.
  • Mesa llvmpipe через ANGLE GL использует --use-angle=gl. ANGLE обращается к системной libGL, а Mesa связывает её с llvmpipe при отсутствии аппаратного GPU. Точки входа WebGL1, WebGL2 и WebGPU остаются доступными, и в настройке нет флага с пометкой unsafe.
  • Mesa lavapipe через ANGLE Vulkan: программный растеризатор Vulkan. Ему нужны расширения Vulkan, которые ANGLE ожидает для WebGL2, а их поставляют не все версии Mesa.
БэкендНеобходимые флагиАдаптер WebGPUWebGL1WebGL2Совместимость в будущем
Mesa llvmpipe (рекомендуется)--use-angle=gl --bot-gpu-emulation=falseдададада
SwiftShader--disable-gpu --enable-unsafe-swiftshader --use-gl=angle --ignore-gpu-blocklistдададаустаревающий и защищённый unsafe-флагом
Mesa lavapipe, bare metal, Ubuntu 22.04--use-angle=vulkan --enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLEнет (null)данетда на Ubuntu 24.04 и новее
Mesa lavapipe, Docker, любой дистрибутивте женет (null)нетнетнепригоден для production
Чистый --disable-gpuтолько --disable-gpuнет (null)нетнетработает только с дополнительными флагами

Свойство navigator.gpu присутствует во всех строках. Колонка WebGPU показывает, возвращает ли navigator.gpu.requestAdapter() рабочий адаптер. О том, как раскрывается адаптер и что он выдаёт, см. Снятие отпечатков WebGPU: следующее поколение отслеживания GPU: там разобраны детали адаптера и способы их контролировать.

К lavapipe стоит присмотреться внимательнее, потому что его показатель CPU выглядит заманчиво. Пакет Mesa 23.2 в Ubuntu 22.04 не содержит всех расширений Vulkan, которые ANGLE нужны для WebGL2. На bare metal WebGL1 всё ещё работает, но WebGL2 завершается ошибкой, а адаптер WebGPU равен null. В Docker загрузка Vulkan ICD также ненадёжна: lavapipe часто вообще не запускается, и WebGL1 тоже перестаёт работать. Ubuntu 24.04 с Mesa 24.2 или новее улучшает ситуацию на bare metal, но поведение в контейнерах по-прежнему ненадёжно. Вернитесь к lavapipe после обновления хостов и пока считайте его непроизводственным вариантом для проверенной конфигурации.

Проекты upstream ясно описывают свои роли. README ANGLE называет ANGLE слоем, переводящим вызовы OpenGL ES в другие графические бэкенды, включая Vulkan и desktop OpenGL; поэтому одного значения --use-angle достаточно для переключения Chromium между тремя растеризаторами. Репозиторий SwiftShader описывает CPU-реализацию графического API Vulkan, независимую от оборудования. Документация Mesa относит llvmpipe к поддерживаемым программным драйверам Gallium. Вместе эти источники объясняют, почему llvmpipe: поддерживаемый программный путь, а не аварийный обход.

Флаг SwiftShader: ещё и вопрос времени. Chromium пометил этот путь как защищённый unsafe-флагом, что указывает на возможное прекращение поддержки, но публичной даты удаления нет. Если флаг когда-нибудь уберут, зависящие от него конвейеры потеряют WebGL, поэтому ранняя миграция превращает вынужденное переключение в запланированное изменение.

Почему чистый --disable-gpu удаляет адаптеры WebGL и WebGPU

Многие руководства по Chromium в Linux предлагают --disable-gpu как однострочное исправление проблем рендеринга на сервере. В современном Chromium этот флаг сам по себе отключает поиск адаптера WebGPU и оба контекста WebGL. navigator.gpu остаётся, но requestAdapter() возвращает null, а getContext('webgl') и getContext('webgl2') завершаются ошибкой. Canvas 2D продолжает работать, поэтому проблема часто обнаруживается только на странице, которой нужен WebGL.

Многие production-развёртывания обходят проблему, добавляя escape-hatch-флаги поверх --disable-gpu:

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

У каждого флага в этом наборе своя задача. --enable-unsafe-swiftshader оставляет путь SwiftShader доступным, --enable-unsafe-webgpu включает программный WebGPU, --use-gl=angle принудительно подключает ANGLE, а --ignore-gpu-blocklist пропускает список блокировки GPU Chromium. На пути llvmpipe они не нужны.

Этот набор из пяти флагов возвращает WebGL1, WebGL2 и адаптер. Но он привязывает развёртывание к SwiftShader и к четырём флагам с unsafe или ignore в названии. После каждого обновления Chromium приходится проверять, не изменилось ли поведение одного из них.

Есть ещё одна ловушка. --disable-gpu имеет приоритет над --use-angle=gl и в headed, и в headless. Если добавить флаг Mesa, но оставить --disable-gpu, llvmpipe не включится, и будет казаться, что миграция не сработала.

Самый чистый выход: удалить --disable-gpu и четыре escape-hatch-флага, заменив всю группу двумя флагами из следующего раздела. Оператор, который может назвать набор из пяти флагов, набор из двух и объяснить, почему чистый --disable-gpu удаляет поиск адаптера, понимает всю миграцию.

Конфигурация llvmpipe из двух флагов

Сначала установите пользовательские пакеты Mesa, через которые ANGLE получает доступ к llvmpipe:

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

Затем запустите Chromium с двумя флагами. Для стандартного headless дисплей не нужен:

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

Для headed-сессии на виртуальном дисплее уберите --headless и задайте дисплей:

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 направляет ANGLE через системный стек OpenGL, а Mesa загружает llvmpipe при отсутствии аппаратного GPU. --bot-gpu-emulation=false позволяет реальному GL-драйверу рисовать WebGL, сохраняя шум Canvas 2D и вариативность --bot-noise-seed. Флаг намеренно узкий: он не отключает профиль или остальную защиту отпечатка.

--bot-gpu-emulation принимает три значения. false: настройка этой миграции. true: стандартный режим по умолчанию. priority добавляет приоритетное планирование GPU для нагрузок с множеством параллельных контекстов в одном экземпляре браузера, работает независимо от выбора GL-бэкенда и не нужен, когда false передаёт GPU-работу реальному драйверу.

При миграции существующего развёртывания сначала удалите эти флаги, а затем добавьте два новых. Некоторые конфликтуют с --use-angle=gl, и любой из них может отменить изменение без ошибки.

Флаг для удаленияПричина
--disable-gpuОтключает поиск адаптера и оба контекста WebGL и имеет приоритет над --use-angle=gl
--enable-unsafe-swiftshaderНужен только для сохранения SwiftShader
--use-gl=swiftshaderЯвно включает SwiftShader и заменяется llvmpipe
--use-gl=angleСтарая форма, заменённая --use-angle=gl, может конфликтовать с ним
--ignore-gpu-blocklistНе нужен: llvmpipe отсутствует в списке блокировки
--enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLEФиксирует путь lavapipe, который отключает WebGL2 на Ubuntu 22.04 bare metal
--use-angle=vulkanПринудительно выбирает тот же путь lavapipe
--disable-vulkan-surfaceОтносится только к Vulkan-пути

В контейнер добавьте те же четыре пакета Mesa и передайте те же два флага при запуске. Параметр --shm-size=2g даёт Chromium больше общей памяти и повышает стабильность. Помните, что именно lavapipe ломается в контейнерах, поэтому для контейнерного развёртывания особенно важно оставаться на llvmpipe через ANGLE GL.

Сохраните --headless, уже используемый --no-sandbox, все флаги --bot-*, включая --bot-profile и --bot-noise-seed, а также сетевые настройки и --user-data-dir. В запусках Playwright или Puppeteer те же флаги передаются в список args:

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

Различия вывода растеризаторов и воспроизводимость seed

Разные программные растеризаторы дают разные пиксели для одного и того же шейдера. После перехода со SwiftShader на Mesa llvmpipe точные байты readPixels или toDataURL изменятся. Это ожидаемое поведение двух растеризаторов, а не признак неудачной миграции.

Поля, которые страница читает как идентификаторы, остаются под контролем профиля. User-Agent, платформа и немаскированные строки vendor и renderer задаются профилем и не меняются вместе с бэкендом. Поведение --bot-noise-seed также не меняется: один и тот же seed воспроизводит один и тот же результат внутри выбранного бэкенда, а другой seed даёт другой стабильный результат.

Отсюда следуют два практических правила. Храните эталонные снимки отдельно для каждого бэкенда, а не сравнивайте байты SwiftShader и llvmpipe. При сравнении до и после миграции используйте один бэкенд и один seed, чтобы ожидаемая разница растеризаторов не скрыла настоящую регрессию.

Канарейка для Linux-флота

Перед изменением всего флота проверьте миграцию на одном канареечном хосте. Последовательность сохраняет наблюдаемость каждого шага:

  1. Установите на канареечный хост libgl1-mesa-dri, libglx-mesa0, libegl-mesa0 и libvulkan1.
  2. Замените набор GPU-флагов на --use-angle=gl --bot-gpu-emulation=false для одного экземпляра и перезапустите его: изменения флагов читаются только при запуске.
  3. Убедитесь, что контексты WebGL1 и WebGL2 создаются, а navigator.gpu.requestAdapter() возвращает адаптер, отличный от null.
  4. Откройте chrome://gpu и проверьте, что строки WebGL, WebGL2 и WebGPU показывают программный рендеринг через ANGLE и OpenGL, а не отключённое состояние. Там же видны активные строки ANGLE и драйвера, подтверждающие использование llvmpipe.
  5. Сравните CPU с сопоставимой базовой нагрузкой SwiftShader в том же headed или headless режиме и при той же нагрузке.
  6. Повторите проверки для одинакового и разного seed, затем распространите изменение на остальной флот.

В таблице сопоставлены частые симптомы и их обычные причины.

СимптомОбычная причинаИсправление
Адаптер null и оба контекста WebGL не работаютЧистый --disable-gpu или lavapipe в DockerУдалите --disable-gpu и Vulkan-флаги, оставьте только два флага
WebGL1 работает, WebGL2 и адаптер nulllavapipe на bare metal со старой MesaУдалите Vulkan-флаги и переключитесь на --use-angle=gl
libGL error: failed to load driver: swrastНе установлены пользовательские пакеты MesaУстановите libgl1-mesa-dri, libglx-mesa0 и libegl-mesa0
chrome://gpu всё ещё показывает SwiftShaderФлаг снова принудительно включает его, например --use-gl=swiftshaderУдалите флаг и перезапустите процесс
CPU не снизилсяСтандартный headless, где доминирует нагрузкаЭто ожидаемо; ценность: стабильность и совместимость в будущем
Изменился вывод пикселей WebGLДругой растеризаторЭто ожидаемо; пересоздайте эталонный снимок для нового бэкенда

Сопоставимое сравнение делает показатель CPU надёжным. Используйте один хост, профиль, нагрузку и режим для обоих бэкендов. Выполняйте нагрузку достаточно долго, например около 25 секунд Canvas 2D вместе с шейдером WebGL2. Суммируйте CPU всех процессов Chromium экземпляра, повторите запуск минимум два раза и усредните результаты, чтобы краткий всплеск нагрузки хоста не исказил вывод. Экономия в одном режиме ничего не говорит о другом, поэтому запускайте baseline в режиме поставки. О том, как проверять вывод Canvas, WebGL и WebGPU в разных бэкендах, см. Проверка приватности в разных графических backend: там описаны матрица рендеринга и контролируемый порядок тестов.

Будьте готовы к тому, что CPU не изменится. В стандартном headless рендеринг идёт в буфер вне экрана при любом бэкенде, поэтому работа Canvas и WebGL доминирует, а оба варианта стоят примерно одинаково. Миграция всё равно даёт стабильные возможности и меньший набор флагов без зависимости от unsafe-флагов.

BotBrowser документирует путь Linux GPU, в котором --use-angle=gl вместе с --bot-gpu-emulation=false позволяет Mesa llvmpipe отрисовывать WebGL, сохраняя шум Canvas 2D и воспроизводимость --bot-noise-seed, поэтому вы можете проверить миграцию из двух флагов на канареечном хосте, прежде чем менять остальной парк. BotBrowser не может сделать llvmpipe быстрее возможностей хоста, не гарантирует экономию CPU в стандартном headless, не может сохранить одинаковые байты WebGL между растеризаторами и не контролирует график устаревания SwiftShader в Chromium; флаг --bot-gpu-emulation требует ENT Tier 2.

Для базовой настройки хоста прочитайте руководство по headless-серверу и руководство по Docker. О поведении seed между бэкендами см. воспроизводимость noise seed. Полный список флагов приведён в руководстве по Linux GPU backend.

Публичные источники

Практический итог

Уберите --disable-gpu и четыре обходных флага, установите четыре пакета Mesa и запустите с --use-angle=gl --bot-gpu-emulation=false на одном канареечном хосте, прежде чем менять остальной парк. Затем повторите ту же нагрузку примерно на 25 секунд в том режиме, который действительно используется в продакшене: экономия около 49% в headed ничего не говорит о headless по умолчанию, а сравнение seed на двух сессиях должно оставаться, чтобы различия вывода растеризаторов были видны.

#Chromium#Linux#Gpu#Mesa#Swiftshader#Webgl#производительность#Benchmark#headless#Xvfb

Эта статья входит в руководство: Развёртывание и выпуск браузера: операционная карта

Переведите BotBrowser из исследований в продакшн

Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.