1. What is webassembly?
2. Why use webassembly
Make “native” modules less complex
Runtimes (such as Node or Python’s CPython) often allow you to write modules in low-level languages (such as C++). This is because these low-level languages are usually much faster. So you can use native modules in Node, or extended modules in Python. But these modules are often hard to use because they need to be compiled on the user’s device. With WebAssembly’s “native” modules, you can get about the same speed and avoid the complexity.
Easier sandboxing to run native code
On the other hand, low-level languages like Rust won’t expect WebAssembly to run faster, but they will use WebAssembly for security. But they will use WebAssembly for security, and as we discussed in the WASI announcement, WebAssembly provides you with lightweight sandboxing by default. So, a voice like Rust can sandbox native code modules with WebAssembly.
Share Native Code Across Platforms
Developers can save development time and reduce maintenance costs if they can share the same code base across different platforms (for example, in Web and desktop applications). This is true for both scripting languages and low-level languages, and WebAssembly gives you a way to do this without degrading the performance of these platforms.
3.1 JIT (just in time) in v8
- The advantage is that it starts fast, because you don’t need to compile it in advance.
- The downside is that let’s say you have a for loop, which means you have to translate the same line of code over and over again, doing the same thing, without being able to do some optimization.
- The advantage is that because it is translated in advance, the code can be optimized before running, which speeds up the runtime.
- The disadvantage is that it is too slow to start and has to be compiled first.
Then JIT technology is the original JS only Interpreter technology added to the Compiler! In the process of real-time translation with interpreter added some features of the compiler, such as a line of code is executed many times, js engine will set it to " Warm" for a series of super-optimization, and then “Hot” for the ultimate optimization when it is executed again.
For example, in js, because types are dynamic, the type of each element in an array is not certain, it could be object, it could be string, it could be number, which means that when you iterate each element of the array, you have to do a series of type checks and so on. When JIT technology is introduced, our js engine may run into the case that the first ten elements are all number, and then boldly predict that the next ones will also be number (of course, they will be checked later).
3.2 Why webassembly is faster
Ok, after the JIT of js, let’s summarize the process of executing js and webassembly.
first look at the fetching part, webassembly code is more compact, because js to be more human-readable, so the code mentioned compared to assembly language will be larger. 2. parse/decode process, js need to first into ast, and then through ast to generate IR (intermediate representation), IR and then generate machine code (x86 or arm).
parse/decode process, js needs to be converted into ast, then through ast to IR (intermediate representation), IR then generate machine code (x86 or arm). webassembly does not need this conversion process. See the figure below. You can see that webassembly can generate machine code directly.
the process of compile + optimize is described in the JIT section, the js engine has to optimize while running, let’s say watch the type of data change or something like that, while webassembly is closer to the underlying machine code, the data type or something is fixed.
In addition, there is also the process of reoptimization in JS. In the type specialization section of the JIT, it is mentioned that the js engine has to predict the type in order to improve performance, and there are definitely times when it fails, so there is a need for reoptimization in the execution of js.
As for the execution part, because webassembly is more low-level (see the following subsection for the two formats of webassembly, wasm and wat formats) than js, even if the final machine code is generated, the degree of optimization that the code written by the webassembly developer must be greater than the optimization that can be done by js.
the GC process is easy to understand. gc in high-level languages that can be converted to webassembly requires manual processing by the developer, while it is automatic in js.
3.3 What does webassembly look like? (wasm format and wat format)
After all this talk, what does webassembly really look like?
Let’s write a simple c++ method as follows:
wasm suffix file: the executable file format that is put directly on the webassembly virtual machine, we use the
Emscriptentool to generate a wasm file from the above c++ file, the command is:
emcc -O3 -s "EXPORTED_FUNCTIONS=['_addAll']" -o test .wasm test.c --no-entry, which exports the addAll method in the wasm file, and the resulting wasm is a binary (actually hexadecimal) file. Open the text.wasm file as follows.
00 61 73 6D 0D 00 00 00 01 86 80 80 80 00 01 60 01 7F 01 7F 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 96 80 80 80 00 02 06 6D 65 6D 6F 72 79 02 00 09 5F 5A 35 61 64 64 34 32 69 00 00 0A 8D 80 80 80 00 01 87 80 80 80 00 00 20 00 41 2A 6A 0B
files with wat suffix: files that are easily human-readable and can be coded on this format, using the wasm2wat tool to convert the generated wasm to wat format,
wasm2wat test.wasmgenerates The contents of wat are as follows: it is more human-readable. For a brief introduction, there are only four data types supported in webassembly.
- i32: 32-bit integer
- i64: 64-bit integer
- f32: 32-bit float
- f64: 64-bit float
i32.subThis is an arithmetic instruction, the first two variables pushed into the stack are the two arguments of the arithmetic instruction, so you can see that this instruction is concise enough.
(module (type (;0;) (func (result i32))) (type (;1;) (func (param i32) (result i32))) (type (;2;) (func)) (type (;3;) (func (param i32))) (func (;0;) (type 2) nop) (func (;1;) (type 1) (param i32) (result i32) local.get 0 i32.const 1 i32.lt_s if ;; label = @1 i32.const 0 return end local.get 0 i32.const 1 i32.sub i64.extend_i32_u local.get 0 i32.const 2 i32.sub ... // Omitted
Of course wasm and wat formats are interchangeable, depending on whether you want to read it or use it.
3.4 Communication in webassembly and js
As we said in the previous summary, there are only four data types in webassembly, and they are all numeric. Our c++ accumulation function only passes the number n, which represents the number of accumulations, so how do we pass complex data structures like string or object between webassembly and js? The answer is to pass a buffer of memory, which is kind of like passing a pointer of a number type between the two, and then putting the content to be passed into this shared memory. See mdn’s
WebAssembly.Memory api for more details here.
In js, you can manipulate binary data buffer by typedArray.
4. write a webassembly demo
4.1 c++ implementation of an accumulation function
We use the above demo to implement a 1 + 2 + 3 + … + n in c++.
4.2 Generating .wasm files with emscripten
The above section mentions the use of emscripten to generate the test.wasm file.
4.3 How to call the generated .wasm file in js
We try to use the exported
addAll method of this wasm file in node as follows.
Because webassembly is now a web standard, various js engines have the corresponding api (WebAssembly) to call webassembly. the usage is very simple, if you are interested go to mdn and search for additional information.
4.4 Rough comparison of computational performance
js and webassembly execute
0 + 1 + 2 + ... + 50000 on my computer is webassembly: 0.07ms; js: 4.886ms; just a simple calculation shows the performance difference.
5. runtime for webassembly
In addition to the browser and node, we talk about two webassembly runtimes, the first one is wasmer, the official website says that this runtime can run on any device, it looks more like a docker container and can run wasm. use it to run our cumulative wasm.
In addition, wasmr also provides a tool called wapm, which is a bit like npm, and some users on its community will upload their own compiled wasm toolkit, which you can download and run directly in wasmer.
There will even be a
wapm_packages and a
.lock file under the wapm project, similar to our package.lock.
This runtime was developed by the Chinese team at intel and is intended to run on top of iot devices with the following supported platform architectures.
ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested)
AArch64 (Cortex-A57 and Cortex-A53 are tested)
The runtime was compiled locally according to the tutorial and was able to run our cumulative wasm method successfully.
The generated runtime command line file iwasm is only 212k.
6. webassembly now in use scenarios
In the w3c online conference on August 29, 2020, several technology majors introduced their scenarios with webassembly respectively:
Typical scenario 1: bilibili, using webassembly to check video content when users upload videos and generate recommended covers based on the videos, all these operations are implemented in the user’s browser (front-end).
intel on embedded devices, using Webassembly to implement a set of application frameworks.
Unity game engine also has webassembly implementation.
Emulator (emulator) such as game boy emulator.
some media processing sites, squoosh, ogv.js, Photon, etc.