Elysia Tools
Navegación
Web Technologies
WebAssembly (WASM) Computación de Alto Rendimiento
WebAssembly para computación de alto rendimiento en el navegador con velocidad casi nativa
Ejemplos
Entradas de esta colección
Integración Básica de WebAssembly
Cargar y usar módulos WebAssembly en JavaScript
Dificultad
4/10
Tiempo estimado
15 min
Etiquetas
wasm, webassembly, performance, integration
Requisitos previos
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();Procesamiento de Imágenes WebAssembly
Procesamiento de imágenes de alto rendimiento con WASM
Dificultad
6/10
Tiempo estimado
20 min
Etiquetas
wasm, image processing, graphics, performance
Requisitos previos
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 en Web Workers
Ejecutar computaciones WASM en hilos de fondo
Dificultad
7/10
Tiempo estimado
25 min
Etiquetas
wasm, workers, multithreading, performance
Requisitos previos
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();Integración Rust WebAssembly
Compilar Rust a WebAssembly para máximo rendimiento
Dificultad
8/10
Tiempo estimado
30 min
Etiquetas
rust, wasm, performance, matrix operations
Requisitos previos
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();
*/Herramientas
Herramientas que suelen usarse con este ejemplo
Relacionado