Ir para o artigo
← Voltar para engenharia

O Electron não é o gargalo do seu gravador de tela

Ilustração da capa para Electron não é o gargalo do seu gravador de tela

Resumo — O elétron tem um custo real de memória. Não é necessário impor uma penalidade significativa de gravação ou exportação.

No nosso Mac mini M4, um gravador nativo do ScreenCaptureKit e o mesmo gravador nativo hospedado no Electron produziram vídeo 4K a 57,70 e 57,53 fps. Um shader de edição 4K levou 1,62 ms por frame no p95 em Metal direto e 1,90 ms através do caminho WebGL-para-Metal do Electron. Uma exportação controlada em 1080p H.264 rodou a 7,54x o tempo real pelo VideoToolbox nativo e 7,46x através do caminho WebCodecs do Electron.

O intervalo não era zero. Apenas não estava onde o argumento convencional o coloca.

A perda clara do Electron foi a memória: 45 MB para o host de gravação nativo direto versus 94 MB para o host Electron/Node assinado, antes de adicionar um renderizador Chromium. Uma sessão Tight Studio empacotada se estabilizou em torno de 744–749 MB neste teste. Isso é uma troca que vale a pena nomear honestamente. Não é uma evidência de que os quadros capturados devem passar por uma página da web ou que a exportação deve recorrer à codificação por software.

Nós construímos Tight Studio com Electron, então temos interesse nessa questão. É por isso que fizemos o benchmark controlado e repetível, e por isso este post inclui os resultados que fazem o Electron parecer pior, assim como aqueles que fazem parecer bom.

Diagrama mostrando o Electron manipulando controles de produto enquanto captura nativa, renderização GPU com suporte Metal e codecs de hardware lidam com os caminhos de mídia

“Native vs Electron” é o nível errado de abstração

Um aplicativo de desktop não é um mecanismo de execução único.

O Electron fornece um renderizador Chromium, um processo principal Node.js e um shell de aplicativo multiprocessos. Ele também suporta módulos nativos. A própria documentação do Electron é explícita ao afirmar que um aplicativo pode usar código nativo para APIs de plataforma e trabalho crítico de desempenho.

Isso significa que um gravador de tela Electron pode ser construído de pelo menos duas maneiras muito diferentes:

  1. Capture, componha, copie e codifique frames através de JavaScript e superfícies do navegador.
  2. Use o Electron para interface do produto e orquestração, enquanto ScreenCaptureKit, AVFoundation, Metal, VideoToolbox ou outro motor nativo de mídia controla o caminho principal.

Esses aplicativos compartilham um rótulo de framework. Eles não compartilham uma arquitetura de desempenho.

O Electron já alimenta aplicativos de desktop exigentes

Essa arquitetura não é incomum. As distribuições atuais de macOS do Codex e Claude usam Electron. Na máquina usada para este artigo, o Codex 26.825.41651 declara ElectronAsarIntegrity para seu app.asar pacote, enquanto Claude 1.26832.0 inclui ambos Electron Framework.framework e app.asar.

A própria documentação do Electron também cita Visual Studio Code, Figma, Docker Desktop, Loom, Canva, Notion, 1Password, Slack, Discord e Signal entre os produtos construídos com o framework. Eles abrangem edição e depuração de código, gráficos colaborativos, gerenciamento de contêineres, gravação de tela, gerenciamento de credenciais, mensagens, voz e vídeo, e fluxos de trabalho de IA.

Essa lista não é um benchmark de desempenho, e não prova que todo aplicativo Electron é eficiente. Ela demonstra o ponto arquitetônico: escolher o Electron para um shell de desktop não exige que o shell execute toda operação cara. Módulos nativos, processos de GPU, serviços locais e sistemas remotos podem ser responsáveis pelo trabalho especializado.

Você pode reproduzir a verificação de pacote macOS sem ferramentas especiais. No Finder, escolha Mostrar conteúdo do pacote, então inspecione Contents/Info.plist, Contents/Resources/app.asar, e Contents/Frameworks/.

Tight Studio usa o segundo modelo. No macOS, os quadros da tela são capturados por um módulo Swift usando ScreenCaptureKit e são gravados com AVAssetWriter. A gravação não passa pelo DOM, React ou um canvas do Chromium. Durante a edição e exportação, a composição da GPU e as APIs de codec de hardware fazem o trabalho pesado; o JavaScript coordena o pipeline.

A Apple descreve o ScreenCaptureKit como sua API de alto desempenho para captura de quadros e áudio. O Electron não impede que um app a chame. Um módulo nativo pode chamar o mesmo framework, receber o mesmo CMSampleBuffer objetos, e entregá-los ao mesmo codificador do sistema.

O que nós avaliamos

Evitamos comparar dois produtos finalizados. Um aplicativo pode renderizar legendas, movimento do cursor, um recorte de câmera e cinco sobreposições, enquanto outro remuxa a gravação original. O resultado mais rápido quase nada nos diria sobre Swift ou Electron.

Em vez disso, mantivemos a carga de trabalho constante:

  • Máquina: Apple M4 Mac mini, CPU de 10 núcleos, GPU de 10 núcleos, 16 GB de memória, macOS 26.5.2.
  • Gravação: o mesmo mecanismo de captura nativo empacotado, executado uma vez do seu CLI direto em Swift e uma vez do executável assinado Electron/Node de Tight Studio. Ambos gravaram o mesmo display animado de 3840×2160 a 60 fps.
  • Edição: o mesmo fundo procedural, cartão arredondado, grade, sombra e shader de cursor animado em 3840×2160. O nativo usou Metal; o Electron usou WebGL 2 através do renderizador Metal do ANGLE. Cada quadro teve um limite de sincronização para que um canvas oculto não pudesse fazer o trabalho desaparecer.
  • Exportar: 300 quadros em 1920×1080, 30 fps, H.264 e alvo de 12 Mbps. Nativo usou Metal mais VideoToolbox. Electron usou WebGL mais WebCodecs com aceleração de hardware solicitada.
  • Execuções: tres por caminho. A tabela apresenta as medianas.

Nenhum resultado de bateria foi incluído. Este era um Mac mini, e uma reivindicação credível de bateria necessita de um teste MacBook mais longo e controlado.

Gráficos de benchmark base zero comparando gravação nativa direta e híbrida com Electron, edição 4K e taxa de exportação H.264

Resultados

FaseNativo diretoElectron/híbridoDiferença do Electron
Taxa de saída de gravação 4K57,70 fps57,53 fps-0.29%
Gravando CPU do host7.06%6.98%-0,09 pontos
Gravando CPU do serviço os31.34%32.76%+1,42 pontos
Gravando pico de memória do host45,36 MB94,39 MB+49,03 MB
Taxa de transferência do shader de edição 4K684,23 fps593,77 fps-13.22%
Tempo de quadro p95 do shader de edição 4K1,62 ms1,90 ms+0,28 ms
Taxa de transferência de exportação 1080p226,10 fps223,78 fps-1.02%
Velocidade de exportação 1080p7,54x tempo real7,46x tempo real-1.02%

Estes são testes curtos e controlados em uma máquina. Eles estabelecem o que é possível com essas arquiteturas; não são uma promessa de que todo app Electron será tão eficiente.

Gravando: o Electron não precisa tocar em um frame

O resultado da gravação é quase um empate porque ambos os caminhos são iguais onde importa.

ScreenCaptureKit produz os quadros. AVAssetWriter e a pilha de codecs do sistema os codificam. O lado do Electron pede ao gravador nativo para iniciar, parar, pausar e retomar. Ele não recebe buffers de pixels 4K através de um canal IPC e não os codifica em JavaScript.

Ao longo das três execuções, o nativo entregou uma mediana de 57,70 fps e o host Electron entregou 57,53 fps — uma diferença de 0,29%. A CPU mediana do gravador foi de 7,06% para o nativo e 6,98% para o host Electron. Os serviços de captura do macOS tiveram uma média de 31,34% e 32,76%, respectivamente.

O resultado da taxa de quadros é o importante. A pequena reversão de CPU é ruído comum de execução para execução, não evidência de que o Electron de alguma forma acelere o ScreenCaptureKit.

Há uma peculiaridade de teste que vale a pena divulgar. macOS concede permissão de Gravação de Tela a uma identidade de aplicativo assinada. Nosso binário Electron de desenvolvimento não tinha essa permissão, então a execução de gravação do Electron usou o executável assinado de Tight Studio no modo compatível com Node do Electron. Isso isola a ponte nativa, mas omite um renderizador do Chromium. Medimos o shell empacotado separadamente em vez de apresentar silenciosamente o host de 94 MB como um app completo do Electron.

Edição: Metal traduzido ainda é Metal

O JavaScript não expõe diretamente a API Metal da Apple. Esse fato às vezes é ampliado para uma afirmação muito mais ampla: que o Electron não pode usar renderização de GPU suportada pelo Metal.

No macOS, o ANGLE fornece um backend Metal para OpenGL ES, que é o que o Chromium pode usar por baixo do WebGL. Nosso benchmark do Electron identificou seu renderizador como ANGLE Metal Renderer: Apple M4.

O Direct Metal foi mais rápido. A execução nativa mediana renderizou 684 quadros por segundo; o Electron renderizou 594, uma diferença de 13% no desempenho. O tempo de quadro P95 aumentou de 1,62 para 1,90 ms.

Isso é uma sobrecarga mensurável. Também é 0,28 ms em um orçamento de quadro de 16,67 ms a 60 fps.

Editores reais fazem mais do que um shader, é claro. Eles decodificam vídeo, carregam ou importam texturas, renderizam texto, calculam o estado da animação e respondem a entradas. Uma implementação descuidada pode consumir o orçamento restante com cópias, alocações, IPC síncrona ou trabalho do React. Mas o compositor do navegador não é automaticamente um renderizador de software, e o WebGL em um Mac não é prova de que a GPU foi ignorada.

Quando um caminho WebGL ou WebGPU não é suficiente, o Electron ainda permite um módulo Metal nativo. A arquitetura pode escolher sua válvula de escape por subsistema.

Exportar: o codificador de hardware não se importa qual botão iniciou

VideoToolbox é a interface de baixo nível da Apple para codificadores e decodificadores de hardware. Chromium possui um backend de codificadores macOS VideoToolbox, e o WebCodecs expõe uma preferência por aceleração por hardware para aplicações.

Na nossa execução nativa, o VideoToolbox confirmou a codificação por hardware. A execução no Electron solicitou hardware através do WebCodecs. O WebCodecs não expõe o nome do codificador selecionado, então não podemos afirmar como prova em nível de API a seleção do Electron. Seu desempenho e saída são consistentes com o caminho de hardware: a versão nativa codificou 300 quadros em uma mediana de 1,327 segundos; o Electron levou 1,341 segundos. As saídas diferiram em tamanho em menos de 1%.

Isso resulta em 7,54x versus 7,46x no tempo real—uma diferença de 1%.

Isso não significa que todo exportador Electron seja rápido. A exportação desacelera quando um aplicativo:

  • lê pixels da GPU para cada quadro;
  • copia quadros completos através de JavaScript ou IPC;
  • codifica em software;
  • serializa descompactação, renderização, áudio e codificação de forma desnecessária;
  • mantém toda a saída na memória em vez de transmiti-la;
  • usa o thread da interface do usuário como o trabalhador de renderização.

Essas são escolhas de pipeline, não requisitos impostos pelo Electron.

Uma exportação real do Tight Studio

Microbenchmarks mostram onde o overhead aparece. Um teste de produto nos diz se o pipeline completo é útil.

Também rodamos o fixture de regressão de exportação de cinco clipes existente da Tight Studio três vezes. A linha do tempo de 112 segundos exerce decodificação por clipe, renderização por GPU, áudio, codificação, concatenação e muxing em 1440×1080. Os tempos de exportação foram 81,54, 80,94 e 81,28 segundos. A mediana era 81,28 segundos, ou 1,38x tempo real.

O arquivo gerado teve 112,36 segundos de duração, cerca de 30 fps, com vídeo H.264 e áudio AAC. Este teste não é um índice universal de velocidade de exportação — os meios de origem e efeitos importam — mas é uma aplicação Electron de ponta a ponta exportando mais rápido que a reprodução em um teste de repositório repetível.

Gráfico mostrando um projeto de 112 segundos de Tight Studio exportando em uma mediana de 81 segundos, ou 1,38 vezes o tempo real

A parte que o Electron realmente perde: memória

O Electron incorpora um runtime de navegador multiprocessos. Isso consome memória.

O host de gravação nativo direto atingiu um pico de 45 MB RSS. O host Electron/Node assinado atingiu um pico de 94 MB. Nossa árvore de processo mínima de edição do Electron estava em torno de 360 MB, e a árvore de processo de exportação estava em torno de 394 MB. Uma sessão Tight Studio empacotada com um perfil novo estabilizou em torno de 744–749 MB neste estado particular do aplicativo.

Gráfico de memória base zero comparando hosts de gravação nativos e Electron correspondentes, com contexto separado da árvore de processos do Electron

Esse último número não é uma lei do Electron, e não é uma comparação com aplicativo nativo. É um lembrete para não usar um shell de teste mínimo como camuflagem de marketing.

A memória pode importar em máquinas com recursos limitados. Ela pode criar pressão, aumentar o uso de swap e, indiretamente, consumir mais energia. Mas RAM alocada não é a mesma métrica que registrar CPU, frames perdidos, tempo de quadro da GPU ou taxa de transferência do codificador. Tratar uma como um proxy para todas as outras produz conclusões de engenharia ruins.

O objetivo prático não é “usar nenhuma memória do Chromium.” É manter o tempo de execução do navegador afastado dos caminhos críticos de quadros brutos, fechar objetos de mídia rapidamente, limitar buffers, transmitir saída e manter o trabalho ocioso ocioso.

Uma maneira melhor de avaliar um gravador de tela

Pergunte o que cada subsistema realmente faz:

  • Qual API captura a tela?
  • Onde os quadros são compostos?
  • O backend da GPU é acelerado por hardware?
  • Qual implementação do codificador é selecionada?
  • Quantas cópias de quadro completo acontecem?
  • Os dados de pixel atravessam IPC ou limites do JavaScript?
  • O editor consegue manter 60 fps na resolução desejada?
  • Qual é o tempo de exportação por segundo de saída?
  • Quais são os resultados de CPU, memória, quadros perdidos, energia e temperatura na mesma carga de trabalho?

“Native” e “Electron” são detalhes úteis de implementação. São resultados de benchmark fracos.

A conclusão

Um aplicativo totalmente nativo tem a menor sobrecarga de shell possível e o acesso mais direto às APIs da plataforma. Se duas equipes construírem pipelines igualmente otimizados e com recursos idênticos, o nativo mantém uma vantagem—especialmente na memória e nos últimos incrementos de controle da GPU.

Mas um aplicativo Electron não é obrigado a construir seu motor de mídia a partir de nós DOM e loops em JavaScript. Ele pode capturar através do ScreenCaptureKit, compor em APIs de GPU suportadas pelo Metal, codificar com o motor de mídia de hardware e mover trabalhos críticos de desempenho para módulos nativos ou workers.

Nossas medições encontraram uma diferença de taxa de quadros de gravação de 0,29%, uma diferença de rendimento de shader 4K sintético de 13% e uma diferença de exportação controlada de 1%. Também encontramos uma grande diferença de memória. Esse é o formato honesto da troca.

O framework define padrões. O pipeline define desempenho.

Fontes e reprodução

  • Apple: ScreenCaptureKit
  • Apple: VideoToolbox
  • Electron: código nativo e electron
  • Electron: modelo de processo
  • Electron: Por que Electron e exemplos de aplicativos em produção
  • ANGLE: Suporte a backend de Metal
  • Chromium: codificador videotoolbox macOS
  • W3C: Aceleração de hardware do WebCodecs

O conjunto de testes de benchmark, a tabela de execução bruta, a ressalva de permissão e os limites de interpretação estão sendo preparados para um lançamento público independente. Adicionaremos o link do repositório aqui quando o pacote puder ser clonado e executado de forma independente. Mais máquinas com Apple silicon e um teste de energia controlado MacBook ampliariam esses resultados, mas não estão incluídos nas afirmações acima.