web-dev-qa-db-fra.com

Le JavaScript standard peut-il être converti en asm.js, ou est-ce uniquement pour accélérer les langages de bas niveau de type statique?

J'ai lu la question Comment tester et développer avec asm.js? , et la réponse acceptée donne un lien vers http://kripken.github.com/mloc_emscripten_talk/#/ .

La conclusion de ce diaporama est que " Les langages de type statique et en particulier C/C++ peuvent être compilés efficacement en JavaScript ", donc nous pouvons " attendez-vous à ce que la vitesse du C/C++ compilé atteigne à peine 2 fois plus lentement que le code natif, ou mieux, plus tard cette année ".

Mais qu'en est-il des langages non typés statiquement, comme le JavaScript standard lui-même? Peut-il être compilé en asm.js?

58
Oriol

JavaScript peut-il être compilé en asm.js?

Pas vraiment, en raison de sa nature dynamique. C'est le même problème que lorsque vous essayez de le compiler vers C ou même vers le code natif - vous devrez en fait expédier un VM avec pour prendre en charge ces aspects non statiques. Au moins, un tel VM est possible:

js.js est un interpréteur JavaScript en JavaScript. Au lieu d'essayer de créer un interpréteur à partir de zéro, SpiderMonkey est compilé en LLVM puis emscripten traduit la sortie en JavaScript.

Mais si le code asmjs s'exécute plus rapidement que JS normal, alors il est logique de compiler JS en asmjs, non?

Non. asm.js est un sous-ensemble assez restreint de JS qui peut être facilement traduit en bytecode. Pourtant, vous devez d'abord décomposer toutes les fonctionnalités avancées de JS dans ce sous-ensemble pour obtenir cet avantage - une tâche assez compliquée. Mais les moteurs JavaScript sont conçus et optimisés pour traduire toutes ces fonctionnalités avancées directement en bytecode - alors pourquoi se soucier d'une étape intermédiaire comme asm.js? Js.js prétend être environ 200 fois plus lent que JS "natif".

Et qu'en est-il des langues non typées en général?

Le diaporama en parle à partir de … Juste C/C++? . Plus précisément:

Langues dynamiques

Des runtimes C/C++ entiers peuvent être compilés et le langage d'origine interprété avec une sémantique appropriée, mais ce n'est pas léger

Les compilateurs de source à source de ces langages vers JavaScript ignorent les différences sémantiques (par exemple, les types numériques)

En fait, ces langages dépendent de VM spéciales pour être efficaces

Les compilateurs de source à source perdent pour eux les optimisations effectuées dans ces machines virtuelles

34
Bergi

En réponse à la question générale "est-ce possible?" alors la réponse est que bien sûr, à la fois JavaScript et le sous-ensemble asm.js sont Turing complet donc une traduction existe.

La question de savoir si l'on doit le faire et s'attendre à un avantage en termes de performances est différente. La réponse courte est "non, vous ne devriez pas." Je compare cela à essayer de compresser un fichier compressé; oui, il est possible d'exécuter l'algorithme de compression, mais en général, vous ne devez pas vous attendre à ce que le fichier résultant soit plus petit.

La réponse courte: Le coût de performance des langages à typage dynamique vient de la signification du code; un programme de type statique avec une signification équivalente entraînerait les mêmes coûts.

Pour comprendre cela, il est important de comprendre pourquoi asm.js offre un avantage en termes de performances; ou, plus généralement, pourquoi les langages à typage statique fonctionnent mieux que les langages à typage dynamique. La réponse courte est "la vérification de type au moment de l'exécution prend du temps", et une réponse plus longue inclurait la possibilité améliorée d'optimiser le code de type statique. Par exemple:

function a(x) { return x + 1; }
function b(x) { return x - 1; }
function c(x, y) { return a(x) + b(y); }

Si x et y sont tous deux connus pour être des entiers, je peux optimiser la fonction c en quelques instructions de code machine. S'ils peuvent être des entiers ou des chaînes, le problème d'optimisation devient beaucoup plus difficile; Je dois les traiter comme des ajouts de chaînes dans certains cas et des ajouts dans d'autres cas. En particulier, il existe quatre interprétations possibles de l'opération d'addition qui se produit dans c; il peut s'agir d'un ajout, ou d'un ajout de chaîne, ou de deux variantes différentes de coercition vers chaîne et ajout. Plus vous ajoutez de types possibles, plus le nombre de permutations possibles augmente; dans le pire des cas pour une langue à typage dynamique, vous avez k ^ n interprétations possibles d'une expression impliquant n termes pouvant chacun avoir un nombre quelconque de k types. Dans un langage typé statiquement, k = 1, il y a donc toujours 1 interprétation d'une expression donnée. De ce fait, les optimiseurs sont fondamentalement plus efficaces pour optimiser le code de type statique que le code de type dynamique: il y a moins de permutations à prendre en compte lors de la recherche d'opportunités d'optimisation.

Le point ici est que lors de la conversion d'un code de type dynamique en code de type statique (comme vous le feriez en passant de JavaScript à asm.js), vous devez tenir compte de la sémantique du code d'origine. Cela signifie que la vérification de type se produit toujours (il vient d'être épelé du code typé statiquement) et toutes ces permutations sont toujours présentes pour étouffer le compilateur.

12
killscreen

Quelques faits sur asm.js , qui, espérons-le, clarifient le concept:

  1. Oui, vous pouvez écrire à la main le dialecte asm.js .

    Si vous avez regardé les exemples de asm.js , ils sont très loin d'être conviviaux . Évidemment, Javascript n'est pas le langage frontal pour créer ce code.

  2. Traduire Vanilla Javascript en dialecte asm.js est pas possible.

    Pensez-y - si vous pouviez déjà traduire Javascript standard d'une manière entièrement statique, pourquoi aurait-il besoin de asm.js ? La seule existence de asm.js signifie que les personnes Javascript JIT chez certaines personnes ont renoncé à leur promesse que Javascript ira plus vite sans aucun effort du développeur .

    Il y a plusieurs raisons à cela, mais disons simplement qu'il serait vraiment difficile pour le JIT de comprendre un langage dynamique aussi bon qu'un compilateur statique. Et puis probablement pour les développeurs de bien comprendre le JIT.

En fin de compte, cela revient à utiliser le bon outil pour la tâche. Si vous voulez du code statique et très performant, utilisez [~ # ~] c [~ # ~] / C++ (/ Java ) - si vous voulez un langage dynamique, utilisez Javascript , Python , ...

11
abergmeier

asm.js a été créé par la nécessité d'avoir un petit sous-ensemble de javascript qui peut être facilement optimisé. Si vous pouvez avoir un moyen de convertir javascript en javascript/asm.js, asm.js n'est plus nécessaire - cette méthode peut être insérée directement dans les interpréteurs js.

3
luiseduardohd

En théorie, il est possible de convertir/compiler/transpiler toute opération JavaScript en asm.js si elle peut être exprimée avec le sous-ensemble limité du langage présent dans asm.js. En pratique, cependant, il n'existe actuellement aucun outil capable de convertir JavaScript ordinaire en asm.js (juin 2017).

Dans tous les cas, il serait plus logique de convertir un langage avec typage statique en asm.js, car le typage statique est une exigence de asm.js et son absence l'une des fonctionnalités de JavaScript ordinaire qui fait il est exceptionnellement difficile de compiler en asm.js.

En 2013, lorsque asm.js était chaud, il y avait eu une tentative de compiler un langage typé similaire à JavaScript , mais le langage et le compilateur semblent avoir été abandonnés.

Aujourd'hui, en 2017, les sous-ensembles JavaScipt TypeScript et Flow seraient des candidats appropriés pour la conversion en asm.js, mais les principales équipes de développement d'aucune langue ne sont intéressées par une telle conversion. LLJS avait une fourchette qui pourrait être compilée en asm.js, mais ce projet est à peu près mort. ThinScript est une tentative beaucoup plus récente et est basée sur TypeScript, mais il ne semble pas non plus être actif.

Ainsi, la meilleure et la plus simple façon de produire du code asm.js est toujours d'écrire votre code en C/C++ et de le convertir/compiler/transpiler. Cependant, il reste à voir si nous voulons même le faire dans un avenir prévisible. Web Assembly pourrait bientôt remplacer complètement asm.js et il y a déjà des langages de type TypeScript comme TurboScript et AssemblyScript qui se convertissent en Web Assembly. En fait, TurboScript était à l'origine basé sur ThinScript et utilisé pour la compilation en asm.js, mais ils semblent avoir abandonné cette fonctionnalité.

2
John Slegers

Il peut être possible de convertir du JavaScript normal en ams.js en commençant par en le compilant en C ou en C++ , puis en compilant le code généré en asm.js en utilisant Emscripten . Je ne sais pas si ce serait pratique, mais c'est quand même un concept intéressant.

Plus récemment, j'ai trouvé un autre outil appelé NectarJS qui compile JavaScript en WebAssembly et ASM.js.

1
Anderson Green

vérifiez cela http://badassjs.com/post/43420901994/asm-js-a-low-level-highly-optimizable-subset-of

fondamentalement, vous devez vérifier que votre code serait compatible avec asm.js (pas de coercition ou de transtypage, vous devez gérer la mémoire, etc.). L'idée derrière cela est d'écrire votre code en javascript, de détecter le goulot d'étranglement et de faire les changements dans votre code pour utiliser asm.js et aot compilation au lieu de jit et la compilation dynamique ... est un peu PITA mais vous pouvez toujours utiliser javascript ou autre langages comme c ++ ou mieux..dans un avenir proche, lljs .....

1
clagccs