- La tendance récente à réécrire des outils Node.js en Rust, Zig, Go ou d'autres langages plus rapides est préoccupante, et voici une synthèse des inquiétudes objectives à ce sujet
[Performance]
- On peut penser que toutes les pistes pour accélérer les outils JavaScript n'ont pas encore été pleinement explorées
- Il existe encore beaucoup de points faciles à améliorer dans ESLint, Tailwind, etc.
- Dans le navigateur, JavaScript est « suffisamment rapide » pour la plupart des charges de travail
- Alors pourquoi vouloir abandonner JavaScript pour les outils CLI ?
Réécritures de grande ampleur
- Pendant longtemps, l'écosystème des outils JavaScript s'est concentré sur le fait que « ça fonctionne »
- Désormais, les API sont pour la plupart stabilisées et tout le monde veut « la même chose, mais plus vite »
- De nouveaux outils peuvent être plus rapides parce qu'ils sont conçus dès le départ avec la performance en tête, et parce que les API étant déjà définies, cela fait gagner du temps de développement
- Lorsqu'on réécrit A en B, on obtient un gain de vitesse, et il est alors facile d'affirmer que B est plus rapide que A
- Mais il se peut aussi que la réécriture elle-même soit la raison de cette amélioration (parce qu'on en sait plus la deuxième fois, et qu'on accorde davantage d'attention aux performances)
Bytecode et JIT
- Dans le navigateur, on bénéficie naturellement du cache de bytecode et du JIT (compilateur Just-In-Time)
- Si JavaScript est correctement mis en cache, le navigateur n'a pas besoin d'analyser ni de compiler le code source en bytecode
- Les fonctions souvent exécutées sont davantage optimisées en code machine (JIT)
- Les scripts Node.js ne bénéficient pas du tout du cache de bytecode
- Mais il est désormais possible d'utiliser un cache de compilation aussi dans Node (
NODE_COMPILE_CACHE via variable d'environnement)
- Le JIT nécessite d'exécuter une fonction plusieurs fois pour qu'elle « chauffe », si bien qu'il est difficile d'en tirer profit dans des scripts exécutés une seule fois
- Dans Pinafore, il a été envisagé de remplacer une bibliothèque blurhash en JavaScript par une version Rust (Wasm), mais à la 5e itération, l'écart de performance disparaît
- On peut envisager de compiler en AOT des scripts Node avec des outils comme Porffor
- L'utilisation de Wasm entraîne une baisse de performance par rapport à des outils purement natifs
[Contribution et facilité de débogage]
- C'est le principal motif de scepticisme vis-à-vis du mouvement consistant à « tout réécrire en natif »
- JavaScript est un langage populaire grâce à son typage permissif, sa facilité d'apprentissage et sa prise en charge par les navigateurs
- Pendant longtemps, dans l'écosystème JavaScript, auteurs de bibliothèques et utilisateurs ont tous deux utilisé JavaScript
- Cela contribue à abaisser la barrière à la contribution
- Mais cet avantage disparaît lorsque les auteurs de bibliothèques JavaScript utilisent une autre langue
- Il est également simple de modifier localement une dépendance JavaScript (en l'éditant directement dans
node_modules)
- À l'inverse, lorsqu'elle est écrite dans un langage natif, il faut récupérer le code source et le compiler soi-même
- Pour déboguer une bibliothèque JavaScript, on peut utiliser les outils de développement du navigateur ou le débogueur Node.js, qui sont familiers
- Le débogage en Wasm n'est pas impossible, mais il exige un autre ensemble de compétences techniques
[Conclusion]
- L'arrivée d'une nouvelle génération d'outils pour l'écosystème JavaScript est une bonne chose
- Les outils existants sont très lents et ont visiblement à gagner de la concurrence
- Mais cela ne signifie pas que JavaScript soit intrinsèquement lent, ni qu'il n'y ait plus de marge d'amélioration
- Quand on regarde les améliorations récentes des outils de développement de Chromium, on a le sentiment qu'il reste encore beaucoup à faire
- Il y a une inquiétude à l'idée d'un monde qui deviendrait le domaine exclusif des développeurs Rust et Zig
- Le développeur JavaScript moyen peut se sentir impuissant lorsqu'il se retrouve face à un bug dans un outil de build
- Cela pourrait apprendre une forme d'impuissance acquise aux jeunes développeurs web
- C'est une voie encore inconnue, qui peut entraîner des conséquences non intentionnelles
- À l'inverse, il existe d'autres chemins, moins risqués, qui peuvent produire presque le même résultat
- Pourtant, la tendance actuelle ne montre aucun signe de ralentissement
L'avis de GN⁺
- Réécrire en Rust, Zig, etc. n'est pas toujours forcément la meilleure solution. Il semble rester davantage de marge d'amélioration côté JavaScript, notamment avec le compile cache
- On peut se demander s'il est vraiment souhaitable d'exposer les développeurs débutants à des problèmes complexes comme les segfaults. Cela pourrait au contraire ne leur apprendre qu'un sentiment d'impuissance
- Il faut se demander si accélérer les choses au prix des atouts d'un écosystème construit de longue date autour de JavaScript (modification libre entre bibliothèques, environnement de débogage familier, etc.) est réellement la bonne direction
- Les efforts d'amélioration des bibliothèques JavaScript existantes devraient eux aussi se poursuivre. Le potentiel de JavaScript est encore loin d'avoir été entièrement exploité
- Même s'il semble difficile d'aller à contre-courant de la tendance, cette orientation mérite davantage de discussion et de réflexion sérieuses à l'échelle de la communauté
15 commentaires
Le mode de fonctionnement d’une petite boutique et celui d’une grande enseigne peuvent être un peu différents. Plutôt que d’être critique envers le simple fait de changer, je pense qu’il est plus sain de réfléchir à la signification de ce phénomène.
On peut avoir l’impression qu’on change par goût ou par effet de mode, mais les entreprises ne prennent généralement pas leurs décisions comme ça, n’est-ce pas ?
Python ou JavaScript eux-mêmes sont-ils lents ? Pas forcément.
En revanche, les outils fréquemment utilisés qui reposent sur Python ou JavaScript sont-ils lents ? Je pense que oui.
J’utilise plusieurs appareils à faible consommation, et il y a vraiment beaucoup d’outils d’une lenteur exaspérante..
On retrouve presque exactement le même refrain du côté de la communauté Python.
JavaScript n’est pas écrit en JavaScript, mais la plupart des développeurs JavaScript ne s’en soucient pas. Dire que, pour les « développeurs débutants » ou les « jeunes développeurs web », le fait que JavaScript ne soit pas écrit en JavaScript ne pose pas problème, mais que le fait que les outils de développement JavaScript ne soient pas écrits en JavaScript en soit un, ce n’est pas vraiment très cohérent. En réalité, les développeurs qui s’en préoccupent ne constituent qu’une infime minorité dans les deux groupes.
Même sans nier qu’avec suffisamment d’optimisation on puisse obtenir des performances presque équivalentes, est-ce que cela en vaut vraiment la peine ?
À une époque, écrire des outils de développement en JavaScript plutôt qu’en C++ était simplement devenu plus rentable ; aujourd’hui, on entre dans une période où les écrire en Rust devient plus rentable que de les écrire en JavaScript.
La manière d’inverser la tendance n’est pas de lancer un mouvement consistant à dépenser davantage pour optimiser en JavaScript, mais plutôt de créer les conditions permettant de développer des outils JavaScript efficaces avec des coûts de développement plus faibles. (Cela peut sembler dire à peu près la même chose, mais la différence tient à l’endroit où l’on investit l’effort.)
Je suis d’accord. Je pense qu’il faut redéfinir la rentabilité en la centrant sur les utilisateurs des outils.
J’ai l’impression que, jusqu’à présent, la rentabilité a surtout été évaluée du point de vue des développeurs d’outils plutôt que de celui de leurs utilisateurs. Les inefficacités et les problèmes de performance que doivent subir les utilisateurs ont eu tendance à être relativement relégués au second plan dans les priorités. Personnellement, j’utilise volontiers uv et vite, et si possible, je préfère éviter des outils comme pip ou create-react-app.
J’ai du mal à être d’accord, car je pense qu’un outil CLI doit pouvoir fonctionner sans runtime.
Si on me dit qu’on peut créer un exécutable WASM autonome, comme le dit aussi l’article, il y aura probablement une baisse de performances.
De la même façon qu’écrire une CLI en Java n’est pas courant, je pense qu’il en va de même pour JavaScript.
Il semble que l’auteur fasse la confusion suivante : comme JavaScript est utilisé à la fois pour les SPA et pour le développement d’outils JavaScript, il suppose que les compétences nécessaires autour sont elles aussi les mêmes. À mon avis, les outils JavaScript exigent des compétences en programmation système et en compilation.
Même si la langue est la même, les environnements d’exécution sont différents entre le navigateur et NodeJS, et seuls ceux capables de franchir cet écart pourront contribuer aux outils JavaScript. Puisque les environnements d’exécution diffèrent, ne faudrait-il pas plutôt considérer qu’il s’agit d’écosystèmes distincts ?
Là encore, je pense qu’on surestime le nombre de personnes capables de franchir la frontière entre le développement SPA et celui des outils JavaScript. Il est déraisonnable d’exiger d’un développeur front-end des connaissances comparables à celles de la programmation système. L’utilisateur d’un outil ne peut au fond comprendre que les messages d’erreur ou les symptômes visibles, non ? À mon avis, ce n’est pas un problème qui se résout simplement parce qu’on connaît la langue.
On dirait qu’on mélange outils et bibliothèques. Pour les bibliothèques, je peux être d’accord dans une certaine mesure, mais pour les outils, j’ai des doutes..
Les développeurs d’autres langages ont aussi l’habitude d’avoir des outils écrits en natif, non ?
Personnellement, qu’il s’agisse d’un outil ou d’une bibliothèque, si c’est écrit en JavaScript, des développeurs familiers de JavaScript peuvent les déboguer et, si nécessaire, y contribuer. Mais si c’est réécrit en Rust, les contributions open source finissent par n’être possibles que pour des développeurs Rust. Comme le vivier de développeurs JavaScript est écrasant par rapport à celui de Rust, il peut être plus avantageux pour l’écosystème open source que les outils comme les bibliothèques soient écrits en JavaScript.
Je pense que JavaScript a un environnement d’exécution fragmenté entre les navigateurs et NodeJS, et que, par conséquent, une simple comparaison du nombre d’utilisateurs du langage a ses limites comme argument. Les développeurs backend Spring et les développeurs du JDK, ainsi que les développeurs React/Angular/Vue et les développeurs d’outils JavaScript, ont des centres d’intérêt et des positions différents ; ils sont dans une relation de consommateurs et de producteurs.
Si l’objectif est d’améliorer les performances et l’ergonomie des outils JavaScript, je pense personnellement que changer de langage d’implémentation, qui n’est qu’un moyen, est aussi une option envisageable.
Je pense qu’il est difficile de distinguer clairement les consommateurs des producteurs d’outils de développement. À mesure qu’une entreprise grandit, il arrive souvent qu’elle personnalise sa toolchain ou qu’elle adapte et implémente des plugins supplémentaires selon ses propres règles ; dans ce cas, le simple fait d’utiliser le même langage constitue selon moi un avantage important.
Il arrive aussi souvent que les utilisateurs d’un outil s’intéressent à l’amélioration ou à l’implémentation de l’outil lui-même et finissent naturellement par y contribuer.
Je pense que les personnes qui commencent à s’intéresser à la personnalisation de la toolchain, ou qui s’occupent de ce travail, jouent un rôle qui dépasse celui de simple consommateur, pour devenir des prosumers, voire des producteurs. Dans le cas des plugins, je considère qu’ils évoluent dans le cadre de la convention de plugin située entre producteur et consommateur. Dans cette situation, je suis également d’accord sur le fait qu’utiliser le même langage est utile, tant sur le plan technique qu’en termes de coût de communication, plutôt que de fournir un format de fichier de configuration séparé ou des points d’extension.
En revanche, je ne pense pas que les problèmes de performance des outils JavaScript, ni le problème de latence du JIT de NodeJS, relèvent du champ de décision du consommateur. En effet, les acteurs qui ont conçu cette architecture et ces spécifications de fonctionnement sont les producteurs d’outils et les développeurs du runtime.
Je doute que le simple fait que l’écosystème JavaScript soit vaste signifie qu’il y aura davantage de développeurs capables de contribuer aux bases de code de compilateurs/transpileurs. À mon avis, les frameworks de bibliothèques et les outils fondamentaux relèvent de domaines complètement différents.
Mais il se peut que ce soit justement la réécriture elle-même qui la rende plus rapide -> En y repensant, c’est vraiment très juste...
Je comprends ce point de vue, justement parce qu’il est très sélectif.
Cela dit, sur un autre plan, le fait qu’il existe diverses solutions au-delà de JS est aussi un élément très important du progrès technologique, donc je pense qu’il faut aussi respecter le point de vue inverse !
Avis Hacker News
Certains estiment que JavaScript est intrinsèquement lent. De nombreux ingénieurs ont essayé de l’accélérer, mais il reste plus lent que les langages à typage statique. Pour les programmes de grande taille, les langages où les types sont explicites sont plus adaptés.
JavaScript n’est pas si facile à apprendre et possède un système de prototypes et de types complexe. TypeScript compense cela, mais l’ensemble reste complexe.
Le simple changement de langage peut déjà améliorer fortement les performances. En remplaçant un système existant en JS et PHP par Go, certains ont constaté un gain de performances de 8 à 10 fois.
L’importance du traitement parallèle est sous-estimée. Rust est adapté à l’écriture de code parallèle, alors que JS ne l’est pas.
JavaScript a désormais des performances proches de Java, tout en restant 2 à 4 fois plus lent que C++. Pour gagner en performances, il faut sortir de sa zone de confort.
Les programmes Rust, Zig et Go sont faciles à inspecter dans le code source et à compiler. Apprendre un nouveau langage influence la manière de résoudre les problèmes.
Certains pensent qu’on n’a pas encore épuisé toutes les possibilités d’améliorer les performances des outils JavaScript. Il reste malgré tout plus efficace de construire sur de meilleures bases.
Rspack est une réécriture compatible de Webpack écrite en Rust, avec des performances 5 à 10 fois supérieures. Il peut remplacer Webpack facilement.
Il est facile de modifier localement des dépendances JavaScript, mais Rust comporte moins de bugs, donc nécessite moins souvent ce type de correction. Rust est difficile à apprendre, mais il peut aussi aider à devenir un meilleur programmeur dans d’autres langages.