Introduction
WebAssembly (Wasm) is a binary instruction format designed to be executed efficiently in web browsers. It serves as a complement to JavaScript, allowing developers to write performance-critical code in languages like Rust, C++, and C and run it in the browser. By compiling code to Wasm, it becomes platform-independent and can run at near-native speeds. Rust, a systems programming language known for its safety and performance, has gained popularity in the WebAssembly ecosystem due to its strong guarantees and seamless integration with Wasm. WebAssembly opens up new possibilities for web development by enabling the execution of complex tasks, such as game engines, image processing, and scientific simulations, with impressive performance.
Here is a short video that you might want to watch before continue reading.
Advantages of WebAssembly
Improved performance for computationally demanding jobs is one of WASM's most persuasive features. For instance, WebAssembly can be much faster than regular JavaScript when doing complicated statistical calculations on enormous datasets. This is so that code can be executed considerably more quickly than it can in JavaScript thanks to WebAssembly's highly optimised design.
The portability of WebAssembly is another benefit. Cross-platform applications are simple to develop since WebAssembly code can be generated from a wide variety of languages and executed on any platform that does.
Finally, security is another consideration in the architecture of WebAssembly. Code cannot access sensitive data or run harmful code because of the sandboxed execution environment it offers.
Using WebAssembly in Rust
Rust is a systems programming language that provides memory safety and performance. It is also a great language for writing WebAssembly code. Let's take a look at how to use WebAssembly in Rust.
Setting up the project
To get started, we need to install a tool called wasm-pack. We can use cargo to install the tool
cargo install wasm-pack
Once we have wasm-pack
installed, we can create a new Rust project and add the required functions. We can annotate these functions with the wasm-bindgen
attribute, which takes care of all the things required to call these functions from JavaScript behind the scenes.
Setting up the Rust environment
- Install Rust by following the official Rust documentation.
- Create a new Rust project using
cargo new --lib wasm-tools
. - Navigate to the project directory using
cd wasm-tools
.
Implementing the Fibonacci function in Rust
- Open the
src/lib.rs
file in a text editor. - Replace the default code with the following Rust implementation of the Fibonacci function
#[wasm_bindgen]
pub fn fib(n: usize) -> usize {
match n {
0 => 0,
1 => 1,
_ => fib(n - 1) + fib(n - 2),
}
}
Building the Rust code for WebAssembly
- Open the terminal and navigate to the project directory (
wasm-tools
). - Run the command
wasm-pack build --target web --release
to build the Rust code as a WebAssembly package.
Using on the frontend
- Create an
index.html
file and add basic boilerplate code. - Attach
main.js
script. - Add the following function in the
main.js
file so that we can compare performance of both the functions.
import init, { add, greet, fib, alert_wasm } from './wasm-tools/pkg/wasm_tools.js';
const app = document.getElementById('app');
const btn = document.getElementById('btn');
const btnWasmAlert = document.getElementById('btn-wasm-alert');
btn.addEventListener('click', handleTriggerFib);
btnWasmAlert.addEventListener('click', () => {
alert_wasm('Hello from Wasm');
});
function updateContent(content) {
const div = document.createElement('div');
div.innerHTML = content;
app.appendChild(div);
}
function fibJS(n) {
if (n < 2) {
return n;
}
return fibJS(n - 1) + fibJS(n - 2);
}
async function run() {
await init();
const res = add(1, 2);
updateContent(`1 + 2 = ${res}`);
const res2 = greet('Wasm Tools');
updateContent(res2);
}
function measureExecutionTime(fn) {
return function(...args) {
const start = performance.now();
const result = fn.apply(this, args);
const end = performance.now();
const executionTime = end - start;
return {result, executionTime};
};
}
function handleTriggerFib() {
// JS
const {result: res3, executionTime: time3} = measureExecutionTime(fibJS)(40);
updateContent(`fibJS(40) = ${res3} in ${time3}ms`);
// Wasm
const {result: res4, executionTime: time4} = measureExecutionTime(fib)(40);
updateContent(`fibWasm(40) = ${res4} in ${time4}ms`);
// Web Worker
const worker = new Worker('./worker.js');
const start = performance.now();
worker.addEventListener('message', (event) => {
const {data} = event;
const {res} = data;
const end = performance.now();
updateContent(`fibWorker(40) = ${res} in ${end - start}ms`);
worker.terminate();
});
worker.postMessage({n: 40});
}
run();
Open html file in browser
Visit https://wasm-web-performance.vercel.app to see the application live.
Conclusion
In conclusion, WebAssembly is a powerful tool for optimizing web applications. It provides improved performance, portability, and security, making it an attractive option for web developers looking to optimize their applications. Rust is a great language for writing WebAssembly code, and wasm-pack
makes it easy to compile and consume WebAssembly code in JavaScript.
Source Code
The source code for this project can be found here.
Top comments (0)