WebAssembly Binary Format

What is WebAssembly Binary Format?

WebAssembly Binary Format (.wasm) is a highly optimized, stack-based format that enables code written in languages like C, C++ or Rust to run in web browsers at near-native speed.

Key Advantages of WebAssembly Binary Format

  1. Compactness: The binary format is highly compressed, resulting in smaller file sizes that load faster than equivalent JavaScript code.
  2. Speed: Because it is already compiled, the binary format can be decoded and executed with minimal overhead, enhancing performance.
  3. Cross-Platform Compatibility: The binary format is platform-independent, meaning it can run on any device with WebAssembly support, regardless of the operating system or browser.
  4. Security: WebAssembly binary code runs in a secure, sandboxed environment, isolating it from the system and protecting against potential security risks.

How is WebAssembly Code Compiled to Binary Format?

The process of generating a WebAssembly binary file usually involves these steps:

  1. Writing Code in a High-Level Language: Developers write code in languages such as C, C++, or Rust, which are well-suited for performance-intensive applications.
  2. Compiling to .wasm: Using a WebAssembly compiler, like Emscripten for C/C++ or Rust’s wasm-pack for Rust, the code is compiled into a .wasm binary file. This binary file contains optimized machine code that is ready to be executed by the browser.
  3. Loading and Running in the Browser: JavaScript then loads the .wasm file via the WebAssembly API, allowing the browser to decode and run the binary code.

Structure of WebAssembly Binary Format

  1. Magic Number and Version: The binary format begins with a four-byte “magic number” (\0asm), which indicates the file type as WebAssembly, followed by a version number.
  2. Sections:
    • Type Section: Defines function signatures, specifying the number and type of parameters and return values.
    • Import Section: Lists functions and variables that the module imports from the outside environment.
    • Function Section: Lists the functions defined in the module.
    • Memory Section: Specifies memory requirements for the module.
    • Export Section: Lists the functions, tables, or memories that the module exports to other applications.
    • Code Section: Contains the actual WebAssembly instructions that will be executed.
    • Data Section: Contains any static data required by the program, such as constants.

Example of Binary Representation

A simple add function in WebAssembly might look like this in text format (WAT):

(module
(func $add (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add)
(export "add" (func $add))
)

When compiled to WebAssembly binary format, the above code would be converted into a sequence of binary instructions that are much more compact, resembling the following hexadecimal format:

00 61 73 6D 01 00 00 00 01 07 01 60 02 7F 7F 01 7F 03 02 01 00 07 07 01 03 61 64 64 00 00 0A 09 01 07 00 20 00 20 01 6A 0B

In this form, the binary is compressed, optimized, and ready for rapid decoding by the browser.

Loading and Running a Binary WebAssembly Module in JavaScript

To load and execute a .wasm binary file in JavaScript, you can use the WebAssembly API. Here’s how you might load and call the add function:

  1. Fetch the WebAssembly Binary File: Load the binary file using JavaScript’s fetch API.
  2. Instantiate the WebAssembly Module: Use WebAssembly.instantiate to decode and compile the binary file.
  3. Call the Function: After instantiation, call the function from JavaScript.
fetch('add.wasm')
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes))
.then(({ instance }) => {
console.log(instance.exports.add(10, 20)); // Outputs: 30
});

In this code:

  • fetch(‘add.wasm’): Fetches the .wasm file from the server.
  • response.arrayBuffer(): Converts the response to an array buffer, suitable for WebAssembly.
  • WebAssembly.instantiate(bytes): Instantiates the WebAssembly module from the binary file.
  • instance.exports.add(10, 20): Calls the add function within the Wasm module, passing 10 and 20 as arguments.

Advantages of the Binary Format for Developers and Users

  • Fast Load Times: Since the binary format is compact, .wasm files load quickly over the network.
  • Improved Performance: The binary format allows near-instantaneous execution, as it is decoded and optimized by the browser’s WebAssembly runtime.
  • Low Overhead: Unlike JavaScript, which requires complex parsing and interpretation, the binary format is simpler for browsers to process.
  • Portability: The same .wasm file can be executed on any platform that supports WebAssembly, ensuring consistent behavior across environments.

Leave a Comment