Перейти к статье
← назад к инженерии

Electron — не узкое место программы для записи экрана

Обложка статьи «Electron — не узкое место программы для записи экрана»

TL;DR — Electron действительно требует больше памяти, но не обязан заметно замедлять запись или экспорт.

На нашем Mac mini с M4 нативная программа записи на ScreenCaptureKit и тот же нативный модуль, запущенный из Electron, записали видео 4K с частотой 57,70 и 57,53 кадр/с. Для монтажного шейдера 4K время кадра p95 составило 1,62 мс в прямом Metal и 1,90 мс в цепочке WebGL → Metal через Electron. Контролируемый экспорт H.264 в 1080p шёл в 7,54 раза быстрее реального времени через нативный VideoToolbox и в 7,46 раза — через WebCodecs в Electron.

Разрыв не был нулевым. Он просто не находился там, где традиционно его ожидают.

Очевидный проигрыш Electron — память: 45 МБ у процесса прямой нативной записи против 94 МБ у подписанного процесса Electron/Node ещё до добавления рендерера Chromium. В этом тесте упакованное приложение Tight Studio стабилизировалось на уровне 744–749 МБ. Это реальный компромисс, о котором стоит говорить честно, но он не доказывает, что захваченные кадры должны проходить через веб-страницу или что экспорт обязан использовать программное кодирование.

Tight Studio построен на Electron, поэтому мы заинтересованы в ответе. Именно поэтому тест контролируемый и воспроизводимый, а в статье приведены как выгодные, так и невыгодные для Electron результаты.

Схема: Electron отвечает за интерфейс продукта, а нативный захват, GPU-рендеринг на базе Metal и аппаратные кодеки — за обработку медиа

«Нативное приложение против Electron» — неверный уровень сравнения

Настольное приложение — это не один исполнительный движок.

Electron предоставляет рендерер Chromium, главный процесс Node.js и многопроцессную оболочку приложения. Также поддерживаются нативные модули. Собственная документация Electron ясно указывает, что приложение может использовать нативный код для API платформы и критически важной для производительности работы.

Значит, программу для записи экрана на Electron можно построить как минимум двумя принципиально разными способами:

  1. Захватывать, компоновать, копировать и кодировать кадры средствами JavaScript и браузерного слоя.
  2. Использовать Electron для интерфейса и координации, а горячий путь передать ScreenCaptureKit, AVFoundation, Metal, VideoToolbox или другому нативному медиадвижку.

У этих приложений общий фреймворк, но разная архитектура производительности.

Electron уже лежит в основе требовательных настольных приложений

Такая архитектура не редкость. Актуальные версии Codex и Claude для macOS используют Electron. На компьютере, где готовилась эта статья, Codex 26.825.41651 указывает ElectronAsarIntegrity для своего app.asar пакета, а Claude 1.26832.0 включает и Electron Framework.framework и app.asar.

В документации Electron среди созданных на этом фреймворке продуктов перечислены Visual Studio Code, Figma, Docker Desktop, Loom, Canva, Notion, 1Password, Slack, Discord и Signal. Они охватывают редактирование и отладку кода, совместную работу с графикой, управление контейнерами, запись экрана, работу с учётными данными, обмен сообщениями, голосовую и видеосвязь и ИИ-сценарии.

Этот список — не тест производительности и не доказательство эффективности любого приложения на Electron. Он показывает архитектурный принцип: выбор Electron для настольной оболочки не требует выполнять в ней каждую ресурсоёмкую операцию. Специализированную работу могут брать на себя нативные модули, процессы GPU, локальные службы и удалённые системы.

Проверку пакета macOS можно повторить без специальных инструментов. В Finder выберите Показать содержимое пакета, затем проверьте Contents/Info.plist, Contents/Resources/app.asar, и Contents/Frameworks/.

Tight Studio использует второй подход. В macOS модуль на Swift захватывает кадры через ScreenCaptureKit и записывает их с помощью AVAssetWriter. Запись не проходит через DOM, React или холст Chromium. При монтаже и экспорте тяжёлую работу выполняют GPU-компоновка и API аппаратных кодеков; JavaScript координирует медиаконвейер.

Apple описывает ScreenCaptureKit как высокопроизводительный API для захвата кадров и звука. Electron не мешает приложению обращаться к нему: нативный модуль может вызвать тот же фреймворк, получить те же CMSampleBuffer объекты и передать их тому же системному кодировщику.

Что мы тестировали

Мы избегали сравнения двух готовых продуктов. Одно приложение может рендерить субтитры, движение курсора, вставку с камеры и пять наложений, в то время как другое просто перемультиплексирует оригинальную запись. Более быстрый результат почти ничего бы не сказал нам о Swift или Electron.

Вместо этого мы зафиксировали одинаковую нагрузку:

  • Тестовая система: Mac mini с Apple M4, 10-ядерным ЦП, 10-ядерным GPU и 16 ГБ памяти; macOS 26.5.2.
  • Запись: один и тот же упакованный нативный движок захвата: сначала напрямую из CLI на Swift, затем из подписанного исполняемого файла Electron/Node в Tight Studio. Оба варианта записывали один и тот же анимированный экран 3840×2160 с целевой частотой 60 кадр/с.
  • Редактирование: одинаковые процедурный фон, скруглённую карточку, сетку, тень и шейдер анимированного курсора при 3840×2160. Нативный вариант использовал Metal, Electron — WebGL 2 через рендерер Metal в ANGLE. Для каждого кадра была задана точка синхронизации, чтобы скрытый холст не позволял пропустить работу.
  • Экспорт: 300 кадров с разрешением 1920×1080, частотой 30 кадр/с, кодеком H.264 и целевым битрейтом 12 Мбит/с. Нативный вариант использовал Metal и VideoToolbox, а Electron — WebGL и WebCodecs с запросом аппаратного ускорения.
  • Запуски: по три для каждого варианта. В таблице приведены медианные значения.

Результатов автономности здесь нет: тест проводился на Mac mini, а достоверные выводы о батарее требуют более длительного контролируемого теста на MacBook.

Графики от нулевой отметки: сравнение прямого нативного и гибридного запуска через Electron при записи, монтаже 4K и экспорте H.264

Результаты

ЭтапНативный запуск напрямуюElectron/гибридРазница с Electron
Частота выходных кадров при записи 4K57,70 кадр/с57,53 кадр/с-0.29%
Загрузка ЦП процессом записи7.06%6.98%−0,09 балла
Загрузка ЦП системными службами при записи31.34%32.76%+1,42 балла
Пиковая память процесса записи45,36 МБ94,39 МБ+49,03 МБ
Производительность шейдера при монтаже 4K684,23 кадр/с593,77 кадр/с-13.22%
Время кадра p95 для шейдера при монтаже 4K1,62 мс1,90 мс+0,28 мс
Производительность экспорта в 1080p226,10 кадр/с223,78 кадр/с-1.02%
Скорость экспорта в 1080pВ 7,54 раза быстрее реального времениВ 7,46 раза быстрее реального времени-1.02%

Это короткие, контролируемые тесты на одной машине. Они показывают, что возможно с этими архитектурами; это не обещание, что каждое приложение Electron будет таким эффективным.

Запись: Electron не должен обрабатывать сами кадры

Результат записи почти вничью, потому что оба пути одинаковы там, где это важно.

Кадры создаёт ScreenCaptureKit, а AVAssetWriter и системный стек кодеков их кодируют. Electron только просит нативный модуль начать, остановить, приостановить или возобновить запись. Он не получает пиксельные буферы 4K по IPC и не кодирует их в JavaScript.

За три запуска медианная частота составила 57,70 кадр/с у нативного варианта и 57,53 кадр/с у процесса под управлением Electron — разница 0,29%. Медианная нагрузка процесса записи на ЦП составила 7,06% и 6,98% соответственно. Системные службы захвата macOS в среднем использовали 31,34% и 32,76% ЦП.

Главный результат — частота кадров. Небольшое преимущество Electron по ЦП — обычный разброс между запусками, а не доказательство того, что Electron каким-то образом ускоряет ScreenCaptureKit.

Есть важная особенность теста. macOS выдаёт разрешение «Запись экрана» подписанному приложению. У нашего исполняемого файла Electron для разработки такого разрешения не было, поэтому запись запускалась через подписанный Tight Studio в совместимом с Node режиме Electron. Это изолирует нативный мост, но не включает рендерер Chromium. Память упакованной оболочки мы измерили отдельно, чтобы не выдавать процесс на 94 МБ за полноценное приложение Electron.

Монтаж: Metal через слой трансляции остаётся Metal

JavaScript не предоставляет прямой доступ к API Metal от Apple. Из этого иногда делают гораздо более широкий вывод: будто Electron не может использовать GPU-рендеринг на базе Metal.

В macOS ANGLE предоставляет бэкенд Metal для OpenGL ES, который Chromium может использовать под WebGL. В нашем тесте Electron сообщил рендерер ANGLE Metal Renderer: Apple M4.

Прямой Metal оказался быстрее: медианная производительность нативного запуска составила 684 кадр/с, а Electron — 594 кадр/с, то есть на 13% меньше. Время кадра p95 выросло с 1,62 до 1,90 мс.

Это измеримые накладные расходы: 0,28 мс при бюджете кадра 16,67 мс для 60 кадр/с.

Реальный редактор, конечно, выполняет не один шейдер. Он декодирует видео, загружает текстуры, отрисовывает текст, рассчитывает состояние анимации и обрабатывает ввод. Неаккуратная реализация может потратить оставшийся запас времени на копирование, выделение памяти, синхронный IPC или работу React. Но браузерный компоновщик не становится автоматически программным рендерером, а WebGL на Mac не означает, что GPU обойдён.

Если возможностей WebGL или WebGPU недостаточно, Electron по-прежнему позволяет подключить нативный модуль Metal. Для каждой подсистемы архитектура может выбрать подходящий запасной путь.

Экспорт: для аппаратного кодировщика неважно, какая кнопка его запустила

VideoToolbox — это низкоуровневый интерфейс Apple к аппаратным кодировщикам и декодировщикам. В Chromium есть macOS бэкенд кодировщика VideoToolbox, а WebCodecs предоставляет приложениям возможность выбирать аппаратное ускорение.

В нативном запуске VideoToolbox подтвердил аппаратное кодирование. В варианте с Electron аппаратное ускорение запрашивалось через WebCodecs. WebCodecs не раскрывает название выбранного кодировщика, поэтому подтвердить выбор Electron на уровне API нельзя. Однако производительность и результат соответствуют аппаратному пути: нативный вариант кодировал 300 кадров за медианные 1,327 секунды, Electron — за 1,341 секунды. Размер файлов отличался менее чем на 1%.

Получается в 7,54 против 7,46 раза быстрее реального времени — разница 1%.

Это не означает, что каждый экспортер Electron работает быстро. Экспорт замедляется, когда приложение:

  • считывает пиксели обратно из GPU для каждого кадра;
  • копирует целые кадры через JavaScript или IPC;
  • кодирует программно;
  • без необходимости выполняет декодирование, рендеринг, обработку звука и кодирование строго последовательно;
  • держит весь результат в памяти вместо потоковой записи;
  • использует поток интерфейса для рендеринга;

Это решения при построении медиаконвейера, а не ограничения Electron.

Реальный экспорт Tight Studio

Микротесты показывают, где появляются накладные расходы. Тест продукта показывает, насколько полезен медиаконвейер целиком.

Мы также трижды запустили существующий регрессионный тест экспорта Tight Studio с пятью клипами. Монтажная шкала длительностью 112 секунд проверяет декодирование каждого клипа, GPU-рендеринг, звук, кодирование, объединение и мультиплексирование при разрешении 1440×1080. Экспорт занял 81,54, 80,94 и 81,28 секунды. Медиана — 81,28 секунды, то есть в 1,38 раза быстрее реального времени.

Готовый файл длился 112,36 секунды, содержал видео H.264 примерно с 30 кадр/с и звук AAC. Этот сценарий не даёт универсальной оценки скорости экспорта — она зависит от исходных медиа и эффектов. Но он показывает полноценное приложение на Electron, которое в воспроизводимом тесте экспортирует быстрее реального времени.

График: проект Tight Studio длительностью 112 секунд экспортируется за медианные 81 секунду — в 1,38 раза быстрее реального времени

Где Electron действительно проигрывает: память

Electron встраивает многопроцессную браузерную среду выполнения. За это приходится платить памятью.

Пиковый RSS процесса прямой нативной записи составил 45 МБ, а подписанного процесса Electron/Node — 94 МБ. Минимальное дерево процессов Electron при монтаже занимало около 360 МБ, при экспорте — около 394 МБ. Упакованное приложение Tight Studio со свежим профилем в этом состоянии стабилизировалось на уровне 744–749 МБ.

График памяти от нулевой отметки: сопоставимые нативный и Electron-процессы записи и отдельный контекст полного дерева процессов Electron

Последнее число не является законом Electron и не является сравнением с нативным приложением. Это напоминание не использовать минимальный тестовый каркас в качестве маркетингового камуфляжа.

На компьютерах с ограниченными ресурсами память важна: её нехватка усиливает подкачку и косвенно повышает энергопотребление. Но объём выделенной памяти — не то же самое, что нагрузка на ЦП при записи, пропущенные кадры, время кадра на GPU или производительность кодировщика. Нельзя подменять все эти показатели одним.

Практическая цель — не «обойтись без памяти Chromium», а не допускать браузерную среду выполнения к горячему пути необработанных кадров, вовремя закрывать медиаобъекты, ограничивать буферы, передавать результат потоком и не выполнять лишнюю работу в простое.

Как правильно оценивать программу для записи экрана

Нужно выяснить, что в действительности делает каждая подсистема:

  • Какой API захватывает экран?
  • Где компонуются кадры?
  • Есть ли аппаратное ускорение у графического бэкенда?
  • Какая реализация кодировщика выбрана?
  • Сколько раз кадр копируется целиком?
  • Передаются ли пиксельные данные через IPC или границу JavaScript?
  • Может ли редактор поддерживать 60 кадров в секунду при целевом разрешении?
  • Сколько времени уходит на экспорт одной секунды готового видео?
  • Каковы нагрузка на ЦП, потребление памяти и энергии, пропуски кадров и нагрев при одинаковой нагрузке?

«Нативное приложение» и «Electron» — полезные сведения о реализации, но сами по себе это слабые результаты теста.

Заключение

У полностью нативного приложения минимальны накладные расходы оболочки и наиболее прямой доступ к API платформы. Если две команды создадут одинаково оптимизированные и функционально идентичные медиаконвейеры, нативный вариант сохранит преимущество — особенно в потреблении памяти и тонком управлении GPU.

Приложение на Electron не обязано строить медиадвижок из DOM-узлов и циклов JavaScript. Оно может захватывать экран через ScreenCaptureKit, выполнять компоновку через GPU API на базе Metal, кодировать аппаратным медиадвижком, а критичные к производительности задачи переносить в нативные модули или фоновые процессы.

Мы измерили разницу 0,29% в частоте кадров при записи, 13% в производительности синтетического шейдера 4K и 1% в контролируемом экспорте. Разница в потреблении памяти оказалась большой. Так выглядит этот компромисс без прикрас.

Фреймворк задаёт исходные условия. Производительность определяет медиаконвейер.

Источники и воспроизведение тестов

  • Apple: ScreenCaptureKit
  • Apple: VideoToolbox
  • Electron: нативный код в приложениях Electron
  • Electron: модель процессов
  • Electron: зачем использовать Electron и примеры реальных приложений
  • ANGLE: поддержка Metal в качестве бэкенда
  • Chromium: кодировщик VideoToolbox в macOS
  • W3C: Аппаратное ускорение WebCodecs

Тестовый стенд, исходная таблица запусков, оговорка о разрешениях и ограничения интерпретации готовятся к отдельной публикации. Мы добавим ссылку на репозиторий, когда пакет можно будет клонировать и запускать независимо. Тесты на других компьютерах с Apple Silicon и контролируемое измерение энергопотребления MacBook расширили бы результаты, но в приведённые выводы они не входят.

поделиться на x