Ejercicios resueltos — Capítulo 27¶
Volver al índice · Capítulo original
Ejercicio 1: Fibonacci en Wasm¶
Compila una función de Fibonacci a Wasm con Rust.
Solución¶
Instalar herramientas:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install wasm-pack
Crear proyecto:
cargo new --lib fib-wasm
cd fib-wasm
Cargo.toml:
[package]
name = "fib-wasm"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
src/lib.rs:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
let mut a: u64 = 0;
let mut b: u64 = 1;
for _ in 0..n {
let t = a + b;
a = b;
b = t;
}
a
}
Compilar:
wasm-pack build --target web
Ejercicio 2: Paquete npm con wasm-pack¶
Crea un paquete npm con tu módulo.
Solución¶
wasm-pack build --target bundler
cd pkg
npm publish --access public
Desde otro proyecto:
npm install fib-wasm
import { fibonacci } from 'fib-wasm';
console.log(fibonacci(40));
Ejercicio 3: Porta una función intensiva¶
Porta una función intensiva a Wasm y mide.
Solución¶
JavaScript puro:
function contarPrimos(limite) {
let contador = 0;
for (let n = 2; n <= limite; n++) {
let esPrimo = true;
for (let i = 2; i * i <= n; i++) {
if (n % i === 0) { esPrimo = false; break; }
}
if (esPrimo) contador++;
}
return contador;
}
const inicio = performance.now();
contarPrimos(100000);
console.log('JS:', performance.now() - inicio, 'ms');
En Rust/Wasm:
#[wasm_bindgen]
pub fn contar_primos(limite: u32) -> u32 {
let mut contador = 0;
for n in 2..=limite {
let mut es_primo = true;
let mut i = 2;
while i * i <= n {
if n % i == 0 { es_primo = false; break; }
i += 1;
}
if es_primo { contador += 1; }
}
contador
}
Comparativa típica: Wasm es 5-10× más rápido.
Ejercicio 4: Cloudflare Workers¶
Prueba un módulo Wasm desde Cloudflare Workers.
Solución¶
npm create cloudflare@latest mi-worker
cd mi-worker
wrangler.toml:
name = "mi-worker"
main = "src/index.js"
compatibility_date = "2024-01-01"
src/index.js:
import wasm from './modulo.wasm';
export default {
async fetch(request) {
const instancia = await WebAssembly.instantiate(wasm);
const resultado = instancia.exports.sumar(2, 3);
return new Response(`Resultado: ${resultado}`);
},
};
Despliega:
npx wrangler deploy
Ejercicio 5: Comparar rendimiento¶
Escribe el mismo algoritmo en JS y Rust.
Solución¶
Medir con performance.now():
import init, { calcular } from './pkg/mi_wasm.js';
await init();
// JS
const t1 = performance.now();
const r1 = calcularJS();
console.log('JS:', performance.now() - t1);
// Wasm
const t2 = performance.now();
const r2 = calcular();
console.log('Wasm:', performance.now() - t2);
Recomendación:
- Tareas <10 ms → JS.
- Tareas intensivas (>100 ms) → Wasm.
- Cargas iniciales: el .wasm tarda en descargar.
Ejercicio 6: Web Worker¶
Añade un Web Worker que ejecute el Wasm en segundo plano.
Solución¶
worker.js:
import init, { fibonacci } from './pkg/fib_wasm.js';
let listo = false;
self.onmessage = async (e) => {
if (!listo) {
await init();
listo = true;
}
const { n } = e.data;
const resultado = fibonacci(n);
self.postMessage({ resultado });
};
main.js:
const worker = new Worker('./worker.js', { type: 'module' });
worker.postMessage({ n: 1000 });
worker.onmessage = (e) => console.log('Resultado:', e.data.resultado);
Ventaja: la UI no se bloquea mientras se calcula.