Performance Profiling WebAssembly
Wasm memang cepat, tapi "berapa cepat?" dan "bisa lebih cepat?" memerlukan pengukuran yang akurat. Profiling membantu menemukan bottleneck dan mengoptimasi di tempat yang tepat.
Benchmarking Basics
// JavaScript: gunakan performance.now()
function benchmark(fn, iterations = 1000) {
// Warmup
for (let i = 0; i < 10; i++) fn();
const start = performance.now();
for (let i = 0; i < iterations; i++) fn();
const elapsed = performance.now() - start;
return {
total: elapsed.toFixed(2) + "ms",
perCall: (elapsed / iterations).toFixed(4) + "ms",
};
}
// Bandingkan JS vs Wasm
const jsResult = benchmark(() => jsFibonacci(40));
const wasmResult = benchmark(() => wasmFibonacci(40));
console.table({ js: jsResult, wasm: wasmResult });
Chrome DevTools Profiling
// 1. Performance tab → Record
// 2. Jalankan Wasm code
// 3. Stop recording
// Di flame chart, Wasm functions muncul sebagai:
// - Nama fungsi (jika compile dengan debug symbols)
// - "wasm-function[42]" (tanpa debug symbols)
// Tips: Compile dengan debug info
// Rust:
wasm-pack build --dev // include debug symbols
// C++:
emcc -g math.c -o math.js // include DWARF debug info
Wasm-specific Optimizations
// 1. Minimize JS↔Wasm calls
// ❌ Slow: banyak crossing
for (let i = 0; i < 1000000; i++) {
wasmModule.processPixel(pixels[i]);
}
// ✅ Fast: satu kali crossing, batch processing
wasmModule.processAllPixels(pixelBuffer, 1000000);
// 2. Use SharedArrayBuffer (zero-copy)
// ❌ Slow: copy data ke Wasm memory
const copy = new Uint8Array(wasmMemory.buffer);
copy.set(largeArray);
// ✅ Fast: shared memory, no copy
const shared = new SharedArrayBuffer(largeArray.byteLength);
new Uint8Array(shared).set(largeArray);
// Pass shared buffer ke Wasm
Rust-specific Optimizations
# Cargo.toml — production optimizations
[profile.release]
opt-level = 3 # maximum optimization
lto = true # link-time optimization
codegen-units = 1 # better optimization, slower compile
strip = true # strip debug symbols
# wasm-opt (post-processing)
wasm-opt -O3 -o output.wasm input.wasm
# Bisa mengurangi size 10-20% dan meningkatkan speed
Size Optimization
# Cek ukuran Wasm
ls -lh pkg/module_bg.wasm
# Analisis apa yang memakan space
cargo install twiggy
twiggy top module_bg.wasm
# Menunjukkan fungsi/data terbesar
twiggy dominators module_bg.wasm
# Menunjukkan dependency tree
# Contoh output:
# 45% - alloc::string::String methods
# 20% - serde_json parsing
# 15% - core::fmt (formatting)
# → Hint: kurangi penggunaan String dan serde jika mungkin
Key Metrics
- Load time — Berapa lama download + compile .wasm (streaming compilation membantu)
- Execution time — Bandingkan dengan JS equivalent
- Memory usage — Monitor linear memory growth
- Bridge overhead — Hitung waktu yang dihabiskan di JS↔Wasm crossing
- Binary size — Lebih kecil = load lebih cepat. Target <100KB untuk modul individual