background
Introduction to the
WebAssembly, or WASM, is an experimental, low-end programming language that works with clients inside browsers. WebAssembly is a portable abstract syntax tree designed to compile and run faster than JavaScript. WebAssembly will allow developers to compile in a programming language they are familiar with (initially C/C++ as the goal) and run in a browser using a virtual machine engine. The development team of WebAssembly comes from Mozilla, Google, Microsoft and Apple, representing the four major web browsers Firefox, Chrome, Microsoft Edge and Safari. In November 2017, all four browsers began supporting WebAssembly on an experimental basis. WebAssembly became a Recommendation by the World Wide Web Consortium (W3C) on December 5, 2019, becoming the fourth language of the Web along with HTML, CSS and JavaScript. (from wiki)
What is theWebAssembly
A WebAssembly is a piece of binary code that is essentially a compilation target.
Generating opportunity
JavaScript was born in 1995. JavaScript is an interpreted, weakly typed language that wasn’t designed to run fast, and it certainly wasn’t fast enough in its first decade.
Optimization Stage I: JIT
In 2008, the era of what everyone calls the Performance wars began. Many browsers have added just-in-time compilers, also known as JIts. When JavaScript code is running, the JIT can recognize the patterns in which the code is running and speed up the code based on those patterns.
The basic idea is to add a monitor to the JS engine to compile and store sections of code that might be executed multiple times through the compiler, call them directly the next time, and optimize the sections.
JavaScript performance hit an inflection point with the advent of JIT, with JavaScript executing 10 times faster than before.
As performance improved, JavaScript began to be used in some unexpected areas, such as server-side programming using Node.js. Improved performance enables JavaScript to solve a whole new class of problems.
JIT problems:
- While making execution faster, it also introduces new (mainly memory) performance costs
- JIT’s optimization mechanism can cause performance problems due to type uncertainty
Optimization stage 2: various options
To address the performance problems caused by type uncertainty, a variety of solutions have emerged:
- Microsoft Typescript improves the looser syntax of JS by adding static type checking to improve code robustness.
- Firefox ASm. js is a subset of JS, and the JS engine is optimized for asm.js.
- Google’s Dart/PNaCl introduces a new VIRTUAL machine for browsers to run Dart/C/C++ applications directly to improve performance.
However, each solution has its own problems:
- Typescript still compiles to JS without much performance improvement;
- Asm.js development efficiency is low;
- Dart/PNaCl only works in Chrome;
Eventually, the big guys agreed that asM.js was a promising approach and standardized it into WebAssembly.
WebAssembly may bring another inflection point.
The working principle of
How does JavaScript work in a browser
When you, as a developer, add JavaScript to a page, you have a goal and a problem.
Goal: Tell the computer what to do.
Problem: You don’t speak the same language as the computer.
JavaScript or any other high-level programming language is a human language. They are designed for human cognition, not machines.
The JS engine’s job is to translate your human language into a machine language that a machine can understand.
In programming, there are usually two ways to translate into machine language. We can use an interpreter or a compiler.
With the interpreter, this translation happens almost line by line in real time.
The compiler uses a different approach, which translates ahead of time and records the translation, rather than doing it on the fly.
Advantages and disadvantages of the interpreter
The interpreter can quickly get up and running the code. You don’t have to complete the entire compile phase to start running the code. It can be translated and run line by line.
The interpreter seems a natural fit for JavaScript. Because it’s important for Web developers to be able to run their code quickly. This is indeed why browsers used JavaScript interpreters in the first place.
However, the interpreter’s shortcomings arise when the same code is run more than once. For example, in a loop, it will have to make the same translation over and over again.
Advantages and disadvantages of compilers
Compilers weigh the pros and cons in the opposite way that interpreters do.
It takes more time to start because the compile phase has to take place first. But because you don’t have to repeat the translation in the loop, the code in the loop runs faster.
Another difference is that the compiler has more time to analyze and modify the code so that it can run faster. This modification is called optimization.
The interpreter works at runtime, so there is not enough time to calculate these optimizations during translation.
Just-in-time Compiler (JIT)
A browser without a JIT executes the JavaScript process
To avoid the inefficiencies of the interpreter, which required retranslation of the code each time it went through the loop, browsers began to blend in with compilers.
Different browsers do this in slightly different ways, but the basic idea is the same. They add the monitor as a new widget to the browser engine. The monitor turns on monitoring when the code starts running and records how many times the code has been run and what type of use it has.
Generally speaking, JavaSciript engines have a processing flow that includes an interpreter and an optimized compiler. The interpreter can quickly generate unoptimized bytecode, while optimizing the compiler takes longer, but ultimately produces highly optimized machine code.
👇 🏻
A few concepts:
Ignition | Interpreter in V8 |
---|---|
Turbofan | Optimizing Compiler in V8 engine |
Baseline | The baseline compiler in the SpiderMonkey engine |
IonMonkey | An optimized compiler in the SpiderMonkey engine |
Stub code | A program segment used to replace part of a function |
warm | Used to mark the frequency of code execution. If the same line of code has been run several times, the code is calledwarm |
hot | Used to mark the frequency of code execution. If the same line of code is run many times, the code is calledhot |
To optimize the | To make the code run faster, the optimization compiler makes some assumptions and generates optimized code |
To optimize the | The code falls back to the version compiled by the interpreter or baseline compiler for execution |
V8 (JS engine for Chrome and Node)
SpiderMonkey (JAVASCRIPT engine used by Firefox)
Let’s use SpiderMonkey as an example to elaborate:
Initially, the monitor runs all code only through the interpreter.
Baseline compiler
When a function starts to warm, the JIT sends it out for compilation. The JIT then stores the compiled results.
Each line of the function is compiled separately into a “pile code,” which is indexed by line number and variable type. If the monitor detects that the same code has been executed (with the same variable type) in code execution, the compiled version is fetched.
This helps speed up the code. But as I mentioned earlier, compilers can do more than that. It can also take some time to figure out how the code works most efficiently, and then optimize it.
The baseline compiler performs the optimizations mentioned above. Optimization should not take too long, however, as it can cause code execution to block.
However, if the code is really hot, that is, it runs a lot, then it is worth the extra time to optimize it.
Optimizing the Optimizing Compiler
When a piece of code is hot, the monitor sends it to the optimization compiler. This will create and save another version of the function code that will run faster than the original.
To make the code run faster, the optimization compiler has to make some assumptions.
For example, if you can assume that all objects are created by a particular formal constructor — that is, objects always have the same attribute names added in the same order — then you can take some shortcuts based on that assumption.
By observing the information gathered by code execution on the monitor, the optimization compiler can make a judgment. If something has happened in previous cycles, assume that it will continue to happen.
But, of course, with JavaScript, this is not guaranteed. Even if 99 objects have the same structure, the 100th May be missing an attribute.
Therefore, you need to check your compiled code to make sure that your assumptions are still valid before you run it. If it passes the check, the code is executed. But if it doesn’t, the JIT thinks it made the wrong assumption and purges the optimized version of the code (de-optimized).
In general, optimizing compilers speed up code, but sometimes they cause unexpected performance problems. If the code is continuously optimized and then optimized, it will end up being slower than the code compiled by the baseline compiler.
Most browsers add restrictions to interrupt the potential optimization/de-optimization cycle. If the JIT has done, say, 10 optimizations and is constantly cleaning up the optimized code, it will give up optimizations.
This is JIT. It monitors code execution and optimizes HOT code to make JavaScript run faster. Its presence has improved the performance of most JavaScript applications many times over.
Despite these improvements, JavaScript performance is patchy. To make performance faster overall, there are a number of overhead associated with JIT running, including:
- Optimize and de-optimize
- Memory consumed by the monitor to record monitoring information
- Memory consumption to optimize recovery information
- storage The baseline Memory consumed by compiling versions of different functions of the compiler and optimizer compiler
WebAssembly
Where WebAssembly sits
Early JS:
Current JS:
WebAssembly versus a typical Web application
Looking forward to
In December 2019, it was officially added to the W3C specification as the fourth parallel language with HTML, CSS and JS
The two main points of WebAssembly so far are:
- Suitable for scenarios where a lot of computation is intensive and does not require frequent interaction with JS and DOM, such as audio and video processing, DOM diff
- Code base reuse can be achieved
Learning materials
- Chinese site webassembly.org.cn/
- Supported languages (WebAssembly itself is positioned as a compilation target) github.com/appcypher/a…
- AssemblyScript AssemblyScript is a compiler that converts TypeScript to WebAssembly
- webassembly.studio/