Aller à l’article
← Retour vers Ingénierie

Electron n’est pas le goulot d’étranglement de votre enregistreur d’écran

Illustration de couverture pour Electron n’est pas le goulot d’étranglement de votre enregistreur d’écran

TL ;DR — Electron a un véritable coût en mémoire. Il n’a pas à imposer une pénalité significative d’enregistrement ou d’exportation.

Sur notre mini Mac M4, un enregistreur natif ScreenCaptureKit et le même enregistreur natif hébergé depuis Electron ont produit une vidéo 4K à 57,70 et 57,53 fps. Un shader de montage 4K a pris 1,62 ms par frame au p95 en Metal direct et 1,90 ms via le chemin WebGL-to-Metal d’Electron. Une exportation 1080p H.264 contrôlée a tourné à 7,54x le temps réel via VideoToolbox native et 7,46x via le chemin WebCodecs d’Electron.

L’écart n’était pas nul. Il n’était simplement pas là où l’argument conventionnel le place.

La perte claire d’Electron concernait la mémoire : 45 MB pour l’hôte d’enregistrement natif direct contre 94 MB pour l’hôte signé Electron/Node, avant d’ajouter un moteur de rendu Chromium. Une session Tight Studio empaquetée se stabilisait autour de 744 à 749 MB dans ce test. C’est un compromis qui mérite d’être nommé honnêtement. Ce n’est pas une preuve que les images capturées doivent passer par une page web ou que l’export doit se rabattre sur l’encodage logiciel.

Nous construisons Tight Studio avec Electron, donc nous avons un intérêt pour cette question. C’est pourquoi nous avons rendu le benchmark contrôlé et reproductible, et pourquoi ce post inclut les résultats qui font paraître Electron moins bien ainsi que ceux qui le font paraître bien.

Diagramme montrant Electron gérant les contrôles de produit tandis que la capture native, le rendu GPU pris en charge par Metal, et les codecs matériels gèrent les chemins des médias

« Natifs vs Electron » est le mauvais niveau d’abstraction

Une application de bureau n’est pas un moteur d’exécution unique.

Electron fournit un moteur de rendu Chromium, un processus principal Node.js et une coque d’application multiprocessus. Il prend également en charge les modules natifs. La documentation d’Electron indique clairement qu’une application peut utiliser du code natif pour les API de la plateforme et les travaux critiques en termes de performance.

Cela signifie qu’un enregistreur d’écran Electron peut être construit d’au moins deux façons très différentes :

  1. Capturer, composer, copier et encoder des images via JavaScript et les surfaces du navigateur.
  2. Utilisez Electron pour le produit interface et l’orchestration, tandis que ScreenCaptureKit, AVFoundation, Metal, VideoToolbox ou un autre moteur multimédia natif gère le chemin critique.

Ces applications partagent un label de framework. Elles ne partagent pas une architecture de performance.

Electron alimente déjà des applications de bureau exigeantes

Cette architecture n’est pas inhabituelle. Les distributions actuelles macOS de Codex et Claude utilisent Electron. Sur la machine utilisée pour cet article, Codex 26.825.41651 déclare ElectronAsarIntegrity pour son app.asar package, tandis que Claude 1.26832.0 publie les deux Electron Framework.framework Et app.asar.

La documentation d’Electron mentionne également Visual Studio Code, Figma, Docker Desktop, Loom, Canva, Notion, 1Password, Slack, Discord, et Signal parmi les produits construits avec le framework. Ils couvrent l’édition et le débogage de code, les graphiques collaboratifs, la gestion des conteneurs, l’enregistrement d’écran, la gestion des identifiants, la messagerie, la voix et la vidéo, et les flux de travail AI.

Cette liste n’est pas un benchmark de performance et ne prouve pas que chaque application Electron soit efficace. Elle démontre le point architectural : choisir Electron pour une interface de bureau ne nécessite pas que l’interface effectue chaque opération coûteuse. Les modules natifs, les processus GPU, les services locaux et les systèmes distants peuvent prendre en charge le travail spécialisé.

Vous pouvez reproduire le contrôle du bundle macOS sans outils spéciaux. Dans le Finder, choisissez Afficher le contenu du paquet, puis inspectez Contents/Info.plist, Contents/Resources/app.asar, et Contents/Frameworks/.

Tight Studio utilise le deuxième modèle. Sur macOS, les images de l’écran sont capturées par un module Swift utilisant ScreenCaptureKit et écrites avec AVAssetWriter. L’enregistrement ne passe pas par le DOM, React ou un canevas Chromium. Pendant le montage et l’exportation, la composition et les API de codec matériel de GPU réalisent le travail lourd ; JavaScript coordonne le pipeline.

Apple décrit ScreenCaptureKit comme son API haute performance pour la capture de frames et d’audio. Electron n’empêche pas une application de l’appeler. Un module natif peut appeler le même framework, recevoir le même CMSampleBuffer objets, et les remettre au même encodeur système.

Ce que nous avons benchmarké

Nous avons évité de comparer deux produits finis. Une application pourrait générer des sous-titres, le mouvement du curseur, une découpe de caméra et cinq superpositions tandis qu’une autre remultiplexerait l’enregistrement original. Le résultat le plus rapide nous aurait presque rien appris sur Swift ou Electron.

À la place, nous avons maintenu la charge de travail constante :

  • Machine : Apple M4 Mac mini, processeur CPU 10 cœurs, GPU 10 cœurs, mémoire GB 16, macOS 26.5.2.
  • Enregistrement : le même moteur de capture natif emballé exactement, exécuté une fois depuis son CLI Swift direct et une fois depuis l’exécutable Electron/Node signé de Tight Studio. Les deux ont enregistré le même affichage animé en 3840×2160 à un objectif de 60 fps.
  • Édition : le même arrière-plan procédural, carte arrondie, grille, ombre et shader de curseur animé à 3840×2160. Native utilisait Metal ; Electron utilisait WebGL 2 via le rendu Metal de ANGLE. Chaque image avait une frontière de synchronisation afin qu’un canevas caché ne puisse pas faire disparaître le travail.
  • Exporter : 300 images à 1920×1080, 30 fps, H.264, et un objectif de 12 Mbps. Native utilisait Metal plus VideoToolbox. Electron utilisait WebGL plus WebCodecs avec accélération matérielle demandée.
  • Exécutions : trois par chemin. Le tableau rapporte les médianes.

Aucun résultat de batterie n’est inclus. Il s’agissait d’un Mac mini, et une revendication de batterie crédible nécessite un test MacBook plus long et contrôlé.

Graphiques de référence à zéro comparant l’enregistrement natif direct et hybride Electron, l’édition 4K, et le débit d’exportation H.264

Résultats

PhaseNatif directElectron/hybrideDifférence Electron
4K taux de sortie d’enregistrement57,70 fps57,53 fps-0.29%
Enregistrement de l’hôte CPU7.06%6.98%-0,09 points
Enregistrement OS-service CPU31.34%32.76%+1,42 points
Enregistrement de la mémoire maximale de l’hôte45.36 MB94.39 MB+49.03 MB
4K débit de modification du shader684,23 fps593,77 fps-13.22%
Temps de trame p95 du shader de montage en 4K1,62 ms1,90 ms+0,28 ms
débit d’exportation 1080p226,10 fps223,78 fps-1.02%
vitesse d’exportation 1080p7,54x temps réel7,46x temps réel-1.02%

Ce sont des tests courts et contrôlés sur une seule machine. Ils établissent ce qui est possible avec ces architectures ; ils ne constituent pas une promesse que chaque application Electron sera aussi efficace.

Enregistrement : Electron n’a pas besoin de toucher une image

Le résultat de l’enregistrement est presque à égalité car les deux chemins sont identiques là où cela compte.

ScreenCaptureKit produit les images. AVAssetWriter et la pile de codecs système les encodent. Le côté Electron demande à l’enregistreur natif de démarrer, d’arrêter, de mettre en pause et de reprendre. Il ne reçoit pas 4K tampons de pixels via un canal IPC et il ne les encode pas en JavaScript.

Au cours des trois exécutions, la version native a fourni une médiane de 57,70 fps et l’hôte Electron a fourni 57,53 fps — une différence de 0,29 %. La médiane de l’enregistreur CPU était de 7,06 % pour la version native et de 6,98 % pour l’hôte Electron. Les services de capture macOS ont atteint en moyenne 31,34 % et 32,76 % respectivement.

Le résultat du taux de trame est celui qui est important. La petite inversion CPU est un bruit ordinaire d’une exécution à l’autre, et non la preuve qu’Electron accélère d’une quelconque manière ScreenCaptureKit.

Il y a un point de test qui vaut la peine d’être divulgué. macOS accorde l’autorisation d’enregistrement d’écran à une identité d’application signée. Notre binaire Electron de développement n’avait pas cette autorisation, donc l’exécution de l’enregistrement Electron a utilisé l’exécutable signé de Tight Studio en mode compatible Node d’Electron. Cela isole le pont natif mais omet un moteur de rendu Chromium. Nous avons mesuré le shell emballé séparément plutôt que de présenter discrètement les 94 hôtes MB comme une application Electron complète.

Édition : Metal traduit reste Metal

JavaScript n’expose pas directement le API de Metal d’Apple. Ce fait est parfois étendu à une affirmation beaucoup plus large : qu’Electron ne peut pas utiliser le rendu GPU basé sur Metal.

Le macOS, ANGLE fournit un backend Metal pour OpenGL ES, que Chromium peut utiliser sous WebGL. Notre benchmark Electron a identifié son moteur comme ANGLE Metal Renderer: Apple M4.

Direct Metal était plus rapide. L’exécution native médiane a rendu 684 images par seconde ; Electron en a rendu 594, un écart de débit de 13 %. Le temps de frame P95 est passé de 1,62 à 1,90 ms.

C’est une surcharge mesurable. Elle est également de 0,28 ms sur un budget d’images de 16,67 ms à 60 ips.

Les vrais éditeurs font plus qu’un seul shader, bien sûr. Ils décompressent la vidéo, téléchargent ou importent des textures, rendent le texte, calculent l’état de l’animation et répondent aux entrées. Une implémentation négligente peut consommer le reste du budget avec des copies, allocations, IPC synchrones ou du travail React. Mais le compositeur du navigateur n’est pas automatiquement un rendu logiciel, et WebGL sur un Mac n’est pas une preuve que le GPU a été contourné.

Lorsqu'un chemin WebGL ou WebGPU n’est pas suffisant, Electron permet toujours un module natif Metal. L’architecture peut choisir sa voie de secours par sous-système.

Exporter : l’encodeur matériel ne se soucie pas du bouton qui l’a lancé

VideoToolbox est l’interface de bas niveau d’Apple pour les encodeurs et décodeurs matériels. Chromium dispose d’un backend d’encodeur VideoToolbox macOS, et WebCodecs expose une préférence d’accélération matérielle aux applications.

Lors de notre exécution native, VideoToolbox a confirmé l’encodage matériel. L’exécution Electron a demandé le matériel via WebCodecs. WebCodecs n’expose pas le nom de l’encodeur sélectionné, nous ne pouvons donc pas revendiquer une preuve au niveau API de la sélection dans Electron. Ses performances et sa sortie sont cohérentes avec le chemin matériel : l’encodage natif a pris en moyenne 1 327 secondes pour 300 images ; Electron a pris 1 341 secondes. Les sorties différaient en taille de moins de 1 %.

Cela correspond à 7,54x contre 7,46x en temps réel — un écart de 1 %.

Cela ne signifie pas que chaque exportateur Electron est rapide. L’exportation ralentit lorsque une application :

  • lit les pixels du GPU pour chaque image ;
  • copie des images complètes via JavaScript ou IPC ;
  • encode en logiciel ;
  • sérialise inutilement les étapes de décodage, de rendu, d’audio et d’encodage ;
  • conserve toute la sortie en mémoire au lieu de la diffuser ;
  • utilise le thread interface comme worker de rendu.

Ce sont des choix de pipeline, pas des exigences imposées par Electron.

Un véritable export Tight Studio

Les micro-benchmarks montrent où l’overhead intervient. Un test produit nous dit si le pipeline complet est utile.

Nous avons également exécuté trois fois le dispositif de régression d’exportation existant à cinq clips de Tight Studio. La timeline de 112 secondes teste le décodage par clip, le rendu GPU, l’audio, l’encodage, la concaténation et le multiplexage à 1440×1080. Les temps d’exportation étaient de 81,54, 80,94 et 81,28 secondes. La médiane était de 81,28 secondes, soit 1,38 fois le temps réel.

Le fichier généré avait une durée de 112,36 secondes, environ 30 images par seconde, avec H.264 vidéo et AAC audio. Ce test n’est pas un indicateur universel de vitesse d’exportation—la source des médias et les effets comptent—mais c’est une application Electron de bout en bout exportant plus rapidement que la lecture dans un test de référentiel répétable.

Graphique montrant un projet Tight Studio de 112 secondes exporté en une médiane de 81 secondes, soit 1,38 fois le temps réel

La partie que Electron perd vraiment : la mémoire

Electron intègre un runtime navigateur multiprocessus. Cela coûte de la mémoire.

L’hôte d’enregistrement natif direct a atteint un pic de 45 MB RSS. L’hôte Electron/Node signé a atteint un pic de 94 MB. Notre arbre de processus d’édition Electron minimal était d’environ 360 MB, et l’arbre de processus d’exportation était d’environ 394 MB. Une session Tight Studio empaquetée avec un profil neuf se situait autour de 744–749 MB dans cet état particulier de l’application.

Graphique de mémoire à zéro comparant les hôtes d’enregistrement natifs et Electron appariés, avec un contexte d’arborescence de processus Electron séparé

Ce dernier chiffre n’est pas une loi d’Electron, et ce n’est pas une comparaison avec une application native. C’est un rappel de ne pas utiliser une version test minimale comme camouflage marketing.

La mémoire peut être importante sur des machines limitées. Elle peut créer de la pression, augmenter l’usage du swap et indirectement coûter de l’énergie. Mais l’RAM allouée n’est pas la même mesure que l’enregistrement CPU, les images perdues, le temps de trame GPU ou le débit de l’encodeur. Considérer l’un comme un substitut pour tous les autres produit de mauvaises conclusions en ingénierie.

L’objectif pratique n’est pas de « ne pas utiliser de mémoire Chromium ». Il s’agit de garder l’exécution du navigateur à l’écart des chemins chauds des images brutes, de fermer rapidement les objets média, de limiter les tampons, de diffuser la sortie et de maintenir le travail inactif inactif.

Une meilleure façon d’évaluer un enregistreur d’écran

Demandez ce que chaque sous-système fait réellement :

  • Quel API capture l’écran ?
  • Où les images sont-elles composites ?
  • Le matériel de GPU est-il accéléré par le matériel ?
  • Quelle implémentation de l’encodeur est sélectionnée ?
  • Combien de copies plein cadre se produisent ?
  • Les données de pixels traversent-elles les frontières IPC ou JavaScript ?
  • Est-ce que l’éditeur peut tenir 60 fps à la résolution cible ?
  • Quel est le temps d’exportation par seconde de sortie ?
  • Quels sont les résultats CPU, mémoire, images perdues, consommation d’énergie et thermique sur la même charge de travail ?

« Natif » et « Electron » sont des détails d’implémentation utiles. Ils sont de faibles résultats de référence.

La conclusion

Une application entièrement native a le moindre surcoût de l’interface possible et l’accès le plus direct aux API de la plateforme. Si deux équipes construisent des pipelines identiques en fonctionnalités et également optimisés, le natif conserve un avantage — surtout en mémoire et dans les derniers incréments du contrôle de GPU.

Mais une application Electron n’est pas obligée de construire son moteur multimédia à partir de DOM nœuds et boucles JavaScript. Elle peut capturer via ScreenCaptureKit, composer sur des API GPU soutenues par Metal, encoder avec le moteur multimédia matériel, et déplacer le travail critique en termes de performance vers des modules natifs ou des workers.

Nos mesures ont trouvé un écart de 0,29 % dans le taux d’image enregistré, un écart de 13 % dans le débit du shader synthétique 4K, et un écart de 1 % dans l’exportation contrôlée. Nous avons également trouvé un important écart de mémoire. C’est la forme honnête du compromis.

Le framework définit les valeurs par défaut. Le pipeline définit les performances.

Sources et reproduction

  • Apple : ScreenCaptureKit
  • Apple : VideoToolbox
  • Electron : code natif et electron
  • Electron : modèle de processus
  • Electron : Pourquoi Electron et exemples d’applications en production
  • ANGLE : prise en charge du backend Metal
  • Chromium : encodeur videotoolbox macOS
  • W3C : Accélération matérielle WebCodecs

Le dispositif de référence, le tableau des exécutions brutes, l’avertissement de permission et les limites d’interprétation sont en cours de préparation pour une publication publique autonome. Nous ajouterons le lien du dépôt ici lorsque le package pourra être cloné et exécuté indépendamment. Des machines Apple Silicon supplémentaires et un test de puissance contrôlé MacBook élargiraient ces résultats, mais ils ne sont pas inclus dans les affirmations ci-dessus.

Partager sur X