VT2018 WebAssembly

From air
Jump to navigation Jump to search
Logo WebAssembly

Auteur

  • Nom : Quentin FOMBARON
  • Mail : q.fombaron@outlook.fr
  • Sujet : WebAssembly

Résumé

Dans chaque navigateur que nous utilisons comme Chrome, Firefox, Edge ou Safari, le code est interprété et exécuté par un moteur JavaScript, c'est à lui que revient le travail d'exécuter le code, et uniquement le JavaScript. Malheureusement, JavaScript n'est pas idéal au point de vue des performances pour toutes les tâches que nous voulons effectuer. C'est là qu'intervient WebAssembly, c'est un nouveau type de code qui peut être exécuté dans les navigateurs modernes. Il a été créé pour obtenir de meilleures performances sur le web. Comment cela est-il possible ? C'est un format binaire qui a une petite taille, donc très rapide à charger et à exécuter. La clé est que nous n'écrivons pas WebAssembly, nous le compilons d'autres langages de niveau supérieur comme du C, C++ ou encore du Rust.

Mots clés

  • Navigateur
  • Javascript
  • Performance

Abstract

In each browser we use such as Chrome, Firefox, Edge or Safari, the code is interpreted and executed by a JavaScript engine, it is the responsibility of the browser to execute the code, and only the JavaScript. Unfortunately, JavaScript is not ideal in terms of performance for all the tasks we want to perform. This is where WebAssembly comes in, this is a new type of code that can be executed in modern browsers. It was created to get better performance on the web. How is this possible? It is a low-level binary format that has a small size, so it is very fast to load and execute. The key is that we don't write WebAssembly, we compile it from other higher-level languages like C, C++ or Rust.

Keywords

  • Browser
  • Javascript
  • Performance

Synthèse

Comment ?

WebAssembly extensions

Lorsque le navigateur télécharge le code de WebAssembly, il peut rapidement le transmettre à n'importe quel assemblage machine. Voici à quoi ressemble WebAssembly : il a un format textuel facile à lire (.wat pour WebAssembly Text Format), mais la représentation binaire est ce que l'on fournit réellement au navigateur (.wasm).

WebAssembly

Ce que WebAssembly nous permet de faire est de prendre du code de niveau supérieur comme du C, C++ ou Rust (un langage recent développé par Mozilla) et de le compiler dans ce qu'on appelle un module WebAssembly. Vous pouvez le charger dans votre application web et l'appeler depuis JavaScript. Il est important de préciser que ce n'est pas un remplacement pour JavaScript, au contraire, il fonctionne avec JavaScript.

Pourquoi ?

Dans le besoin d'utiliser un logiciel en dehors du navigateur : jeux vidéo, montage vidéo, rendu 3D ou production musicale. Ces applications font beaucoup de calculs et exigent un haut degré de performance. Ce genre de performance est difficile à obtenir avec JavaScript. JavaScript a commencé comme un simple langage de script destiné à apporter une certaine interactivité sur le web, qui a l'époque était composé uniquement de documents hypertextes légers. Il a été conçu pour être facile à apprendre et à écrire, mais pas pour être rapide. Au fil des ans, les navigateurs ont ajouté des optimisations dans la façon dont ils interprètent JavaScript, ce qui a apporté d'importantes améliorations de performance. Au fur et à mesure que les choses s'accéléraient, la liste des possibilités dans le navigateur a commencé à s'allonger. Les nouvelles API ont apporté des éléments tels que les graphiques interactifs, le streaming vidéo, la navigation hors ligne et bien d'autres choses encore. En retour, de plus en plus d'applications riches, qui n'étaient auparavant que des applications natives, ont commencé à apparaître sur le Web. Aujourd'hui, vous pouvez facilement modifier des documents et envoyer des mails à partir d'un navigateur, mais il y a des domaines où la performance JavaScript est toujours un challenge. Les jeux vidéo sont particulièrement difficiles car ils doivent coordonner non seulement l'audio et la vidéo, mais aussi souvent la physique et l'intelligence artificielle. Etre capable d'atteindre la performance pour faire tourner des jeux sur le web de manière efficace ouvrirait la porte à de nombreuses autres applications sur le web et c'est ce que WebAssembly s'est mis en tête de faire.

Des avantages ?

Voici ce qui rend WebAssembly spécial et si bien adapté au Web : rapidité, portabilité, flexibilité.

Rapidité

WebAssembly a été conçu pour la vitesse. Ses binaires sont beaucoup plus petits que les fichiers JavaScript textuels. En raison de leur taille, ils sont plus rapides à télécharger, ce qui est particulièrement important sur les réseaux lents.

Portabilité

L'un des principaux objectifs de la conception de WebAssembly était la portabilité. Pour exécuter une application sur un périphérique, elle doit être compatible avec l'architecture processeur et le système d'exploitation du périphérique. Cela signifie compiler le code source pour chaque combinaison de système d'exploitation et d'architecture CPU que vous souhaitez prendre en charge. Avec WebAssembly, il n'y a qu'une seule étape de compilation et votre application s'exécutera dans tous les navigateurs modernes.

Flexibilité

Avec WebAssembly, les développeurs Web pourront choisir d'autres langues et plus de développeurs pourront écrire du code pour le Web. JavaScript sera toujours le meilleur choix pour la plupart des cas d'utilisation, mais maintenant il y aura une option pour passer à un langage spécialisé de temps en temps lorsque l'on a vraiment besoin d'un coup de pouce. Des parties comme l'interface utilisateur et la logique applicative peuvent être en JavaScript, avec les fonctionnalités de base de WebAssembly. Lors de l'optimisation des performances des applications JS existantes, les goulets d'étranglement pourraient être réécrits dans un langage mieux adapté au problème.

Conclusion

The end of Javascript ?

JavaScript aura toujours sa place dans le développement web. C'est un langage très puissant, assez flexible pour construire presque n'importe quoi et ces quelques lacunes qu'il ne peut pas bien gérer peuvent maintenant être comblées avec WebAssembly. Compiler JavaScript en WebAssembly n'est pas possible, et cela n'aurait vraiment aucun sens car les navigateurs sont déjà conçus pour fonctionner directement avec JS et maximiser ses performances. Mais même si l'on continue à travailler uniquement avec JavaScript, nous pouvons toujours bénéficier de WebAssembly et des gains de vitesse qu'il apporte, grâce à des bibliothèques et des frameworks améliorés.

Démonstration

Partie 1

The end of Javascript ?

Un simple HelloWorld pour tester le fonctionnement de WebAssemby. L'installation de emsdk est requise pour compiler du C.

#include <stdio.h>
int main(int argc, char ** argv) {
  printf("Hello, world!\n");
}

On compile le code C : emcc hello.c -s WASM=1 -o hello.html

  • -s WASM=1 à emcc pour utiliser WASM, sinon par défaut, c'est asm.js qui est utilisé
  • .html pour génèrer une page HTML

On lance un serveur : emrun --no_browser --port 8080 .

Puis à l'adresse http://localhost:8080/

Demo

Partie 2

Demo2

On écrit un exemple simple en C++ dans le compilateur en ligne

int square (int num) { 
  return num * num;
}

On compile, on obtient alors le code .wat :

(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "_Z6squarei" (func $_Z6squarei))
 (func $_Z6squarei (; 0 ;) (param $0 i32) (result i32)
  (i32.mul
   (get_local $0)
   (get_local $0)
  )
 )
)

Ainsi que le code assembleur :

wasm-function[0]:
  sub rsp, 8                            ; 0x000000 48 83 ec 08
  mov edx, edi                          ; 0x000004 8b d7
  mov ecx, edx                          ; 0x000006 8b ca
  mov eax, edx                          ; 0x000008 8b c2
  imul ecx, eax                         ; 0x00000a 0f af c8
  mov eax, ecx                          ; 0x00000d 8b c1
  nop                                   ; 0x00000f 66 90
  add rsp, 8                            ; 0x000011 48 83 c4 08
  ret

Ce que l'on télécharge est en réalité le fichier .wasm

square.wasm

�asm�����������`�?�?���������������p��������������������������memory��
_Z6squarei��
������������ � �l�

Il suffit ensuite d'importer le fichier binaire .wasm dans le Javascript :

script.js

let squareWASM ;

function loadWebAssembly(fileName) {
    return fetch(fileName)
        .then(response => response.arrayBuffer())
        .then(buffer => WebAssembly.compile(buffer))
        .then(module => {return new WebAssembly.Instance(module)});
}

loadWebAssembly('square.wasm')
    .then(instance => {
        squareWASM = instance.exports._Z6squarei; /*Il faut donner ici le nom présent dans le fichier binaire .wasm commençant par <code>_Z6</code>*/
       document.getElementById("webassembly").innerHTML += '<code>squareWASM(' + 5 + ') = ' + squareWASM(5) + '</code><br>';
    });

Et enfin, importer le script JS dans l'HTML :

index.html

<!DOCTYPE html>
<html lang="fr">

<head>
    <meta charset="utf-8">
    <title>WebAssembly Demonstration</title>
</head>

<body>

<h1>WebAssembly Demonstration</h1>
<script src="script.js"></script>

<h2>Test WebAssembly</h2>
<p id="webassembly"></p>

</body>

</html>

On lance la commande npx serve pour créer un serveur et ainsi éviter l'erreur "Cross-origin resource sharing". On obtient alors le comportement voulu :

Demo3

Sources