Elysia Tools
Navegação
Web Technologies
WebAssembly (WASM) Computação de Alta Performance
WebAssembly para computação de alta performance baseada em navegador com velocidade quase nativa
Exemplos
Entradas desta coleção
Integração Básica WebAssembly
Carregar e usar módulos WebAssembly em JavaScript
Dificuldade
4/10
Tempo estimado
15 min
Etiquetas
wasm, webassembly, performance, integration
Pré-requisitos
JavaScript, WebAssembly basics
// Basic WebAssembly Integration
// C code (compiled to WASM):
/*
int add(int a, int b) {
return a + b;
}
int calculate(int* numbers, int length) {
int sum = 0;
for (int i = 0; i < length; i++) {
sum += numbers[i];
}
return sum;
}
*/
// JavaScript integration
async function loadWasm() {
const response = await fetch('math.wasm');
const buffer = await response.arrayBuffer();
const wasmModule = await WebAssembly.compile(buffer);
const wasmInstance = await WebAssembly.instantiate(wasmModule);
return wasmInstance.exports;
}
// Usage
async function main() {
const wasm = await loadWasm();
// Simple addition
const result = wasm.add(5, 3);
console.log('5 + 3 =', result); // 8
// Array operations
const numbers = new Int32Array([1, 2, 3, 4, 5]);
const pointer = wasm.allocateArray(numbers.length, 4);
// Copy data to WASM memory
const wasmMemory = new Uint8Array(wasm.memory.buffer);
const dataView = new DataView(wasm.memory.buffer);
for (let i = 0; i < numbers.length; i++) {
dataView.setInt32(pointer + (i * 4), numbers[i], true);
}
const sum = wasm.calculate(pointer, numbers.length);
console.log('Sum:', sum); // 15
// Clean up
wasm.deallocateArray(pointer, numbers.length);
}
main();Processamento de Imagem WebAssembly
Processamento de imagem de alta performance com WASM
Dificuldade
6/10
Tempo estimado
20 min
Etiquetas
wasm, image processing, graphics, performance
Pré-requisitos
JavaScript, Canvas API, WebAssembly
// WebAssembly Image Processing
// C++ code compiled to WASM for image manipulation
const wasmCode = `
(module
(memory (export "memory") 1)
(func (export "grayscale") (param $offset i32) (param $size i32)
(local $i i32) (local $pixel i32) (local $gray i32)
(loop $process
(set_local $pixel
(i32.load (get_local $offset))
)
(set_local $gray
(i32.div_u
(i32.add
(i32.add
(i32.and (get_local $pixel) 0xFF)
(i32.shr_u (get_local $pixel) 8)
)
(i32.shr_u (get_local $pixel) 16)
)
3
)
)
(i32.store (get_local $offset)
(i32.or
(i32.or
(get_local $gray)
(i32.shl (get_local $gray) 8)
)
(i32.shl (get_local $gray) 16)
)
)
(set_local $offset
(i32.add (get_local $offset) 4)
)
(br_if $process
(i32.gt_u (get_local $size)
(tee_local $i (i32.add (get_local $i) 1))
)
)
)
)
)
`;
// JavaScript image processor
class WasmImageProcessor {
constructor() {
this.wasmModule = null;
this.wasmInstance = null;
}
async init() {
const buffer = Uint8Array.from(atob(wasmCode), c => c.charCodeAt(0));
this.wasmModule = await WebAssembly.compile(buffer);
this.wasmInstance = await WebAssembly.instantiate(this.wasmModule);
}
async convertToGrayscale(imageData) {
if (!this.wasmInstance) await this.init();
const pixels = new Uint8ClampedArray(imageData.data);
const wasmMemory = new Uint8Array(this.wasmInstance.exports.memory.buffer);
// Copy image data to WASM memory
wasmMemory.set(pixels);
// Process in WASM
this.wasmInstance.exports.grayscale(0, pixels.length / 4);
// Copy processed data back
const processedData = new Uint8ClampedArray(wasmMemory.slice(0, pixels.length));
return new ImageData(processedData, imageData.width, imageData.height);
}
}
// Usage
async function processImage() {
const processor = new WasmImageProcessor();
await processor.init();
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Load and process image
const img = new Image();
img.onload = async () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const grayscale = await processor.convertToGrayscale(imageData);
ctx.putImageData(grayscale, 0, 0);
};
img.src = 'image.jpg';
}WebAssembly em Web Workers
Executar computações WASM em threads de fundo
Dificuldade
7/10
Tempo estimado
25 min
Etiquetas
wasm, workers, multithreading, performance
Pré-requisitos
JavaScript, Web Workers, WebAssembly
// WASM Web Worker for heavy computations
// worker.js
const wasmCode = `
(module
(memory (export "memory") 1)
(func (export "fibonacci") (param $n i32) (result i32)
(local $a i32) (local $b i32) (local $temp i32) (local $i i32)
(if (i32.le_s (get_local $n) 1)
(then (return (get_local $n)))
)
(set_local $a (i32.const 0))
(set_local $b (i32.const 1))
(loop $fib
(set_local $temp (get_local $b))
(set_local $b (i32.add (get_local $a) (get_local $b)))
(set_local $a (get_local $temp))
(br_if $fib
(i32.lt_s
(tee_local $i (i32.add (get_local $i) 1))
(get_local $n)
)
)
)
(return (get_local $b))
)
)
`;
// Initialize WASM in worker
self.addEventListener('message', async (e) => {
const { type, data } = e.data;
if (type === 'init') {
const buffer = Uint8Array.from(atob(wasmCode), c => c.charCodeAt(0));
const wasmModule = await WebAssembly.compile(buffer);
const wasmInstance = await WebAssembly.instantiate(wasmModule);
self.wasm = wasmInstance.exports;
self.postMessage({ type: 'ready' });
}
if (type === 'calculate') {
const { n } = data;
const result = self.wasm.fibonacci(n);
self.postMessage({
type: 'result',
data: { n, result }
});
}
});
// main.js
class WasmWorkerPool {
constructor(workerCount = 4) {
this.workers = [];
this.taskQueue = [];
this.busyWorkers = new Set();
// Initialize workers
for (let i = 0; i < workerCount; i++) {
this.createWorker();
}
}
createWorker() {
const worker = new Worker('worker.js');
worker.addEventListener('message', (e) => {
if (e.data.type === 'ready') {
this.processQueue();
} else if (e.data.type === 'result') {
this.onWorkerComplete(worker, e.data);
}
});
worker.postMessage({ type: 'init' });
this.workers.push(worker);
}
calculate(n) {
return new Promise((resolve) => {
this.taskQueue.push({ n, resolve });
this.processQueue();
});
}
processQueue() {
if (this.taskQueue.length === 0) return;
const availableWorker = this.workers.find(w => !this.busyWorkers.has(w));
if (!availableWorker) return;
const task = this.taskQueue.shift();
this.busyWorkers.add(availableWorker);
availableWorker.postMessage({
type: 'calculate',
data: task
});
}
onWorkerComplete(worker, result) {
this.busyWorkers.delete(worker);
const task = this.taskQueue.find(t => t.n === result.data.n);
if (task) {
task.resolve(result.data.result);
}
this.processQueue();
}
}
// Usage
async function batchCalculate() {
const pool = new WasmWorkerPool(4);
const numbers = [30, 35, 40, 45, 50, 55];
const promises = numbers.map(n => pool.calculate(n));
const results = await Promise.all(promises);
console.log('Fibonacci results:', results);
}
batchCalculate();Integração Rust WebAssembly
Compilar Rust para WebAssembly para performance máxima
Dificuldade
8/10
Tempo estimado
30 min
Etiquetas
rust, wasm, performance, matrix operations
Pré-requisitos
Rust, WebAssembly, wasm-bindgen
// Rust code for WebAssembly (src/lib.rs)
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
// High-performance matrix operations
#[wasm_bindgen]
pub struct Matrix {
data: Vec<f32>,
rows: usize,
cols: usize,
}
#[wasm_bindgen]
impl Matrix {
#[wasm_bindgen(constructor)]
pub fn new(rows: usize, cols: usize) -> Matrix {
Matrix {
data: vec![0.0; rows * cols],
rows,
cols,
}
}
#[wasm_bindgen]
pub fn get(&self, row: usize, col: usize) -> f32 {
self.data[row * self.cols + col]
}
#[wasm_bindgen]
pub fn set(&mut self, row: usize, col: usize, value: f32) {
self.data[row * self.cols + col] = value;
}
#[wasm_bindgen]
pub fn multiply(&self, other: &Matrix) -> Matrix {
assert_eq!(self.cols, other.rows);
let mut result = Matrix::new(self.rows, other.cols);
for i in 0..self.rows {
for j in 0..other.cols {
let mut sum = 0.0;
for k in 0..self.cols {
sum += self.get(i, k) * other.get(k, j);
}
result.set(i, j, sum);
}
}
result
}
#[wasm_bindgen]
pub fn scale(&mut self, factor: f32) {
for value in &mut self.data {
*value *= factor;
}
}
}
// Performance benchmark
#[wasm_bindgen]
pub fn benchmark_fibonacci(n: u32) -> u64 {
if n <= 1 {
return n as u64;
}
let mut a = 0u64;
let mut b = 1u64;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
// JavaScript integration
/*
// Import compiled WASM
import init, { Matrix, benchmark_fibonacci, greet } from './pkg/your_package.js';
async function main() {
await init();
// Matrix operations
const m1 = new Matrix(1000, 1000);
const m2 = new Matrix(1000, 1000);
// Fill matrices with random data
for (let i = 0; i < 1000; i++) {
for (let j = 0; j < 1000; j++) {
m1.set(i, j, Math.random());
m2.set(i, j, Math.random());
}
}
console.time('Matrix multiplication');
const result = m1.multiply(m2);
console.timeEnd('Matrix multiplication');
// Benchmark
console.time('Fibonacci');
const fib = benchmark_fibonacci(50);
console.timeEnd('Fibonacci');
console.log('Fibonacci(50) =', fib);
// DOM interaction
greet('WebAssembly');
}
main();
*/Ferramentas
Ferramentas frequentemente usadas com este exemplo
Relacionado