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 не поддаётся сравнению.
Содержание
- Что показывает измерение
- Почему SwiftShader здесь дороже и чем отличаются три бэкенда
- Почему чистый --disable-gpu удаляет адаптеры WebGL и WebGPU
- Конфигурация llvmpipe из двух флагов
- Различия вывода растеризаторов и воспроизводимость seed
- Канарейка для Linux-флота
Что показывает измерение
У результата есть чёткая граница. Это одна нагрузка headed на виртуальном дисплее, запущенная на хосте Ubuntu 22.04 x86_64 с профилем Windows 11; CPU суммировался через ps по всем процессам Chromium, а среднее взято из двух запусков. Результат не описывает любую нагрузку или любой хост. В стандартном режиме headless оба бэкенда используют почти одинаковый CPU.
| Режим | Бэкенд | Средний CPU | Что это означает |
|---|---|---|---|
| Headed на Xvfb | SwiftShader | ~999% | Базовый уровень |
| Headed на Xvfb | Mesa llvmpipe | ~513% | Примерно на 49% ниже базового уровня |
| Headed на Xvfb | Mesa lavapipe | ~153% | WebGL2 отключён, для production не подходит |
| Стандартный headless | SwiftShader с полным набором флагов unsafe | ~713.5% | Базовый уровень |
| Стандартный headless | Mesa 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.
| Бэкенд | Необходимые флаги | Адаптер WebGPU | WebGL1 | WebGL2 | Совместимость в будущем |
|---|---|---|---|---|---|
| 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-флота
Перед изменением всего флота проверьте миграцию на одном канареечном хосте. Последовательность сохраняет наблюдаемость каждого шага:
- Установите на канареечный хост
libgl1-mesa-dri,libglx-mesa0,libegl-mesa0иlibvulkan1. - Замените набор GPU-флагов на
--use-angle=gl --bot-gpu-emulation=falseдля одного экземпляра и перезапустите его: изменения флагов читаются только при запуске. - Убедитесь, что контексты WebGL1 и WebGL2 создаются, а
navigator.gpu.requestAdapter()возвращает адаптер, отличный от null. - Откройте
chrome://gpuи проверьте, что строки WebGL, WebGL2 и WebGPU показывают программный рендеринг через ANGLE и OpenGL, а не отключённое состояние. Там же видны активные строки ANGLE и драйвера, подтверждающие использование llvmpipe. - Сравните CPU с сопоставимой базовой нагрузкой SwiftShader в том же headed или headless режиме и при той же нагрузке.
- Повторите проверки для одинакового и разного seed, затем распространите изменение на остальной флот.
В таблице сопоставлены частые симптомы и их обычные причины.
| Симптом | Обычная причина | Исправление |
|---|---|---|
| Адаптер null и оба контекста WebGL не работают | Чистый --disable-gpu или lavapipe в Docker | Удалите --disable-gpu и Vulkan-флаги, оставьте только два флага |
| WebGL1 работает, WebGL2 и адаптер null | lavapipe на 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.
Публичные источники
- Выбор Linux GPU backend в BotBrowser
- Документация Mesa llvmpipe
- Репозиторий SwiftShader
- README ANGLE
Практический итог
Уберите --disable-gpu и четыре обходных флага, установите четыре пакета Mesa и запустите с --use-angle=gl --bot-gpu-emulation=false на одном канареечном хосте, прежде чем менять остальной парк. Затем повторите ту же нагрузку примерно на 25 секунд в том режиме, который действительно используется в продакшене: экономия около 49% в headed ничего не говорит о headless по умолчанию, а сравнение seed на двух сессиях должно оставаться, чтобы различия вывода растеризаторов были видны.
Эта статья входит в руководство: Развёртывание и выпуск браузера: операционная карта
Похожие статьи
Проверка приватности в разных графических backend
РазвертываниеНастройка headless BotBrowser на серверах Ubuntu
ОтпечаткиСнятие отпечатков WebGPU: следующее поколение отслеживания GPU
РазвертываниеBotBrowser Trimmed для коротких сессий Linux x64
РазвертываниеСигналы безголового и обычного браузера: метод сравнения
Отпечаткиwebgl_debug_renderer_info: что GPU раскрывает страницам
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.