An Interactive Report on Performance
This report explores a common developer challenge: computationally intensive tasks, like image processing, can be slow in JavaScript, leading to a poor user experience. When applying a filter to a high-resolution image, the browser's main thread can lock up, causing the UI to freeze.
The standard JavaScript approach involves iterating through every pixel of an image on a canvas, which is effective but not always performant enough for a smooth interface.
Experience the difference yourself. Upload an image (or use the default), then apply a grayscale filter using both pure JavaScript and a simulated WebAssembly module. Watch the timers to see the performance gap.
2. Apply grayscale filter
JavaScript Time
- ms
WebAssembly Time
- ms
The performance gain was achieved by surgically replacing the slow JavaScript function with a Rust-based WebAssembly module. This process is more accessible than it sounds. Here is the code from the report, broken down by step.
The core image filtering logic is translated into a Rust function. The structure is very similar to the JavaScript equivalent, but it benefits from Rust's performance and type safety.
// The fast Rust version
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn apply_grayscale_wasm(data: &mut [u8]) {
for i in (0..data.len()).step_by(4) {
let avg = ((data[i] as u32 +
data[i + 1] as u32 +
data[i + 2] as u32) / 3) as u8;
data[i] = avg; // red
data[i + 1] = avg; // green
data[i + 2] = avg; // blue
}
}
A command-line tool, `wasm-pack`, compiles the Rust code into an optimized WebAssembly binary and generates the necessary JavaScript "glue" code to make it usable on the web.
# This one command does it all
wasm-pack build --target web
Finally, the compiled module is imported into the main JavaScript file and its function is called just like any other JS function, after a one-time initialization.
// Import and run the WASM module
import init, { apply_grayscale_wasm } from './pkg/your_wasm_package.js';
async function run() {
await init(); // Initialize the module
// ... get image data from canvas ...
// Call the super-fast Rust function!
apply_grayscale_wasm(imageData.data);
// ... put the data back on the canvas ...
}
run();