Performance e Benchmark
Wasm è Sempre Più Veloce di JavaScript?
La risposta breve è no. WebAssembly è più veloce di JavaScript in scenari specifici, ma i moderni motori JS (V8, SpiderMonkey) sono estremamente ottimizzati. La differenza reale dipende dal tipo di workload.
Dove Wasm Eccelle
Calcolo Intensivo (CPU-bound)
Per operazioni matematiche pesanti, cicli ripetitivi e algoritmi computazionali, Wasm può essere 2-10x più veloce:
// fibonacci.c - Compilato a Wasm
int fibonacci(int n) {
if (n <= 1) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; i++) {
int temp = a + b;
a = b;
b = temp;
}
return b;
}
// Lo stesso in JavaScript
function fibonacci(n) {
if (n <= 1) return n;
let a = 0, b = 1;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
}
Per valori grandi di n, la versione Wasm sarà significativamente più veloce grazie ai tipi statici e all’assenza di garbage collection.
Elaborazione Immagini e Video
// Benchmark: applicare filtro blur a un'immagine 4K
// JavaScript: ~450ms
// Wasm (C++): ~85ms
// Wasm (Rust): ~90ms
// Wasm (SIMD): ~25ms
Crittografia
Le operazioni crittografiche beneficiano enormemente dei tipi interi a 64 bit di Wasm:
// Hashing SHA-256 di 1MB di dati
// JavaScript: ~12ms
// Wasm (C): ~3ms
// Wasm (C + SIMD): ~1.5ms
Dove JavaScript è Competitivo
Manipolazione del DOM
Wasm non può accedere al DOM direttamente. Ogni interazione passa attraverso un bridge JavaScript, annullando i vantaggi di velocità:
// Questo è più veloce in puro JavaScript
document.querySelectorAll('.item').forEach(el => {
el.style.color = 'red';
});
Operazioni I/O
Per fetch, file reading e networking, il collo di bottiglia è l’I/O, non la CPU. Wasm non offre vantaggi in questi scenari.
Codice Business Logic Semplice
Per logica applicativa standard (validazione form, routing, state management), JavaScript è già ottimale e più facile da mantenere.
SIMD (Single Instruction, Multiple Data)
Le istruzioni SIMD permettono di elaborare più dati con una singola istruzione, ideali per:
- Elaborazione immagini
- Operazioni su vettori e matrici
- Machine learning
- Codec audio/video
// Con SIMD: moltiplica 4 float in parallelo
#include <wasm_simd128.h>
void multiply_vectors(float* a, float* b, float* result, int len) {
for (int i = 0; i < len; i += 4) {
v128_t va = wasm_v128_load(&a[i]);
v128_t vb = wasm_v128_load(&b[i]);
v128_t vr = wasm_f32x4_mul(va, vb);
wasm_v128_store(&result[i], vr);
}
}
Threading
WebAssembly supporta i thread tramite SharedArrayBuffer e Web Workers:
// Worker che esegue Wasm
const worker = new Worker('wasm-worker.js');
// wasm-worker.js
const memory = new WebAssembly.Memory({
initial: 256,
maximum: 256,
shared: true, // Memoria condivisa
});
Il multi-threading è particolarmente utile per:
- Ray tracing
- Simulazioni fisiche
- Encoding/decoding media
- Compression
Overhead di Chiamata JS ↔ Wasm
Ogni chiamata tra JavaScript e Wasm ha un piccolo overhead. Per operazioni veloci chiamate migliaia di volte, questo può essere significativo:
// ❌ Lento: molte chiamate piccole
for (let i = 0; i < 1000000; i++) {
wasmModule.processPixel(pixels[i]); // Overhead per ogni chiamata
}
// ✅ Veloce: una sola chiamata con dati batch
wasmModule.processAllPixels(pixelBuffer, 1000000);
Regola: Passa i dati in blocco a Wasm, non un elemento alla volta.
Ottimizzare la Dimensione del Bundle
La dimensione del modulo .wasm impatta il tempo di caricamento:
# Ottimizza con wasm-opt (parte di Binaryen)
wasm-opt -O3 input.wasm -o output.wasm # Massima ottimizzazione
wasm-opt -Oz input.wasm -o output.wasm # Minima dimensione
# Compressione
gzip -9 output.wasm # ~60-70% riduzione
brotli output.wasm # ~70-80% riduzione
Quando Usare Wasm
| Scenario | Usare Wasm? | Motivo |
|---|---|---|
| Image/video processing | ✅ Sì | CPU-intensive, SIMD |
| Game engine | ✅ Sì | Calcolo costante, physics |
| Crittografia | ✅ Sì | i64, operazioni bit |
| Codec audio/video | ✅ Sì | Port di codice C esistente |
| Machine learning | ✅ Sì | Inferenza pesante |
| Form validation | ❌ No | JS è sufficiente |
| DOM manipulation | ❌ No | JS è più veloce (diretto) |
| CRUD app | ❌ No | I/O bound, non CPU |
| Business logic | ❌ No | Overhead di manutenzione |