{"schemaVersion":1,"id":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm","title":"WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly","description":"Shared memory en WebAssembly, atomics, computación paralela, SharedArrayBuffer, explorando WASM threads a través de una implementación de ray tracer para separar la realidad de la exageración.","language":"es","datePublished":"2025-10-31","dateModified":null,"contentFormat":"text/markdown","content":"WebAssembly\n\n# WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly\n\n2025-10-314 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/wasi-threads-shared-memory-parallel-wasm>)\n\n## El modelo de threading\n\nWASM threads usa un modelo de memoria compartida similar a pthreads. Múltiples threads comparten la misma memoria lineal. La sincronización pasa a través de operaciones atómicas sobre esa memoria.\n\n```c\n// Compilar con: emcc -pthread -s SHARED_MEMORY=1 -s PTHREAD_POOL_SIZE=8\n#include <pthread.h>\n#include <stdatomic.h>\n\n#define WIDTH 800\n#define HEIGHT 600\n#define NUM_SAMPLES 64\n\nstatic uint32_t framebuffer[WIDTH * HEIGHT];\nstatic atomic_int next_row;\nstatic atomic_int completed_rows;\n\nvoid* render_thread(void* arg) {\n while (1) {\n int row = atomic_fetch_add(&next_row, 1);\n if (row >= HEIGHT) break;\n\n for (int x = 0; x < WIDTH; x++) {\n float r = 0, g = 0, b = 0;\n for (int s = 0; s < NUM_SAMPLES; s++) {\n Ray ray = camera_ray(x, row, s);\n Vec3 color = trace(ray, scene, 0);\n r += color.x; g += color.y; b += color.z;\n }\n r /= NUM_SAMPLES; g /= NUM_SAMPLES; b /= NUM_SAMPLES;\n framebuffer[row * WIDTH + x] = pack_rgba(r, g, b, 1.0f);\n }\n atomic_fetch_add(&completed_rows, 1);\n }\n return NULL;\n}\n```\n\n## Integración con el browser: Workers + SharedArrayBuffer\n\nEn el browser, cada thread de WASM corre en un Web Worker:\n\n```javascript\nconst memory = new WebAssembly.Memory({\n initial: 256, maximum: 1024, shared: true\n});\n\nconst numThreads = navigator.hardwareConcurrency || 4;\n\nfor (let i = 0; i < numThreads; i++) {\n const worker = new Worker('worker.js');\n worker.postMessage({\n type: 'init', wasmBytes, memory,\n threadId: i, totalThreads: numThreads\n });\n}\n\n// Leer el framebuffer y renderizar al canvas\nconst canvas = document.getElementById('canvas');\nconst ctx = canvas.getContext('2d');\nconst imageData = ctx.createImageData(800, 600);\n\nfunction renderFrame() {\n const pixels = new Uint8ClampedArray(memory.buffer, 0, 800 * 600 * 4);\n imageData.data.set(pixels);\n ctx.putImageData(imageData, 0, 0);\n requestAnimationFrame(renderFrame);\n}\nrenderFrame();\n```\n\nEl requisito crítico: tu página debe configurar headers de seguridad para que ` SharedArrayBuffer ` funcione:\n\n```\nCross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: require-corp\n```\n\nSin estos headers, ` SharedArrayBuffer ` se deshabilita y tu memoria compartida no va a funcionar. Este es el gotcha de deploy más común.\n\n## Performance: los números reales\n\nLos benchmarks del ray tracer revelan resultados significativos. La escena es una Cornell box con 4 esferas, 64 samples por pixel, 800x600:\n\n```\nC nativo (gcc -O3, 8 threads): 1.240ms\nWASM threads (Chrome, 8 workers): 1.890ms (1.52x nativo)\nWASM threads (Firefox, 8 workers): 2.100ms (1.69x nativo)\nWASM single-thread (Chrome): 9.450ms (7.62x nativo)\nJavaScript (optimizado a mano, 8 workers): 14.200ms (11.45x nativo)\n```\n\nWASM threads logra 52-66% del rendimiento nativo. El scaling es casi lineal hasta el conteo de cores físicos:\n\n```\n1 thread: 9.450ms\n2 threads: 4.780ms (1.98x speedup)\n4 threads: 2.410ms (3.92x speedup)\n8 threads: 1.890ms (5.00x speedup)\n```\n\n## WASI threads fuera del browser\n\nLa propuesta ` wasi-threads ` trae el mismo modelo a runtimes WASM del lado servidor:\n\n```bash\nclang --target=wasm32-wasi-threads \\\n -pthread -matomics -mbulk-memory \\\n -Wl,--import-memory,--shared-memory,--max-memory=67108864 \\\n -o ray_tracer.wasm ray_tracer.c\n\nwasmtime run --wasi threads ray_tracer.wasm\n```\n\nEn Rust, el target ` wasm32-wasi-threads ` es experimental pero funcional:\n\n```rust\nuse std::sync::atomic::{AtomicI32, Ordering};\nuse std::sync::Arc;\n\nfn main() {\n let counter = Arc::new(AtomicI32::new(0));\n let mut handles = vec![];\n\n for _ in 0..8 {\n let counter = Arc::clone(&counter);\n let handle = std::thread::spawn(move || {\n for _ in 0..1000 {\n counter.fetch_add(1, Ordering::Relaxed);\n }\n });\n handles.push(handle);\n }\n\n for handle in handles {\n handle.join().unwrap();\n }\n assert_eq!(counter.load(Ordering::SeqCst), 8000);\n}\n```\n\n## Primitivas de sincronización\n\n```c\ntypedef struct { _Atomic int locked; } WasmMutex;\n\nvoid wasm_mutex_lock(WasmMutex* m) {\n while (1) {\n int expected = 0;\n if (atomic_compare_exchange_weak(&m->locked, &expected, 1)) return;\n __builtin_wasm_memory_atomic_wait32(&m->locked, 1, -1);\n }\n}\n\nvoid wasm_mutex_unlock(WasmMutex* m) {\n atomic_store(&m->locked, 0);\n __builtin_wasm_memory_atomic_notify(&m->locked, 1);\n}\n```\n\nEl par ` wait32/notify ` es crucial. Sin ellos, usarías un spin-lock que quema ciclos de CPU. ` wait32 ` le dice al runtime \"dormí este thread hasta que el valor en esta dirección de memoria cambie.\"\n\n## Dónde importa esto\n\nWASM threads desbloquean workloads que antes eran impracticables en el browser:\n\n- **Procesamiento de imagen/video**: Operaciones paralelas de pixels\n- **Computación científica**: Simulaciones Monte Carlo, operaciones de matrices\n- **Motores de juegos**: Simulación de física en threads separados\n- **Compresión**: Compresión de bloques paralela (zstd, brotli)\n- **Inferencia de ML**: Multiplicación de matrices paralela para modelos chicos\n\nWASM threads no son un reemplazo completo del threading nativo. Son una aproximación suficientemente buena que trae paralelismo real a ambientes sandboxeados. Para los workloads que se benefician, y el speedup de 5x del ray tracer con 8 threads prueba que existen, eso alcanza para cambiar lo que es posible.\n\n## Preguntas frecuentes\n\n### ¿Qué son los WASI threads?\n\nWASI threads es una propuesta que agrega creación de threads y soporte de shared memory al WebAssembly System Interface. Permite que módulos WASM creen threads que comparten la misma memoria lineal, habilitando computación paralela real.\n\n### ¿Puedo usar WASM threads en el browser?\n\nSí, via SharedArrayBuffer y Web Workers. Cada worker carga el mismo módulo WASM con memoria compartida. Los headers COOP y COEP deben estar seteados.\n\n### ¿Cómo se compara el rendimiento de WASM threads con nativo?\n\nEn workloads compute-bound, WASM threads logran 60-80% del rendimiento nativo de threads. El overhead viene del bounds checking en acceso a memoria compartida y el costo de creación de workers del browser.\n\n## Tips\n\n1. **Tip:** Utilizar ` memory.atomic.wait32 ` y ` memory.atomic.notify ` para sincronización de threads en vez de spin-locks. Los spin-locks queman ciclos de CPU; wait/notify cede al scheduler.\n2. **Tip:** Siempre compilá con ` -pthread -matomics -mbulk-memory ` cuando apuntés a WASM threads desde C/C++. Si falta algún flag, el binario cae silenciosamente a comportamiento single-threaded.\n3. **Tip:** Configurar los headers ` Cross-Origin-Opener-Policy: same-origin ` y ` Cross-Origin-Embedder-Policy: require-corp ` en tu página HTML. Sin estos, los browsers deshabilitan ` SharedArrayBuffer `.\n4. **Tip:** Perfilar con ` performance.measureUserAgentSpecificMemory() ` para trackear uso de memoria por thread. Los profilers de heap estándar no distinguen memoria shared vs private en WASM.\n\n- wasi\n- wasm\n- threads\n- shared-memory\n- atomics\n- parallel-computing\n- webassembly\n- ray-tracer\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)","headings":[{"level":1,"text":"WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#title"},{"level":2,"text":"El modelo de threading","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#el-modelo-de-threading"},{"level":2,"text":"Integración con el browser: Workers + SharedArrayBuffer","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#integracin-con-el-browser-workers-sharedarraybuffer"},{"level":2,"text":"Performance: los números reales","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#performance-los-nmeros-reales"},{"level":2,"text":"WASI threads fuera del browser","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#wasi-threads-fuera-del-browser"},{"level":2,"text":"Primitivas de sincronización","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#primitivas-de-sincronizacin"},{"level":2,"text":"Dónde importa esto","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#dnde-importa-esto"},{"level":2,"text":"Preguntas frecuentes","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#questions"},{"level":3,"text":"¿Qué son los WASI threads?","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#question-1"},{"level":3,"text":"¿Puedo usar WASM threads en el browser?","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#question-2"},{"level":3,"text":"¿Cómo se compara el rendimiento de WASM threads con nativo?","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#question-3"},{"level":2,"text":"Tips","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#article-tips"}],"sections":[{"heading":"WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly","level":1,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm","content":"WebAssembly"},{"heading":"WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly","level":1,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#title","content":"2025-10-314 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/wasi-threads-shared-memory-parallel-wasm>)"},{"heading":"El modelo de threading","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#el-modelo-de-threading","content":"WASM threads usa un modelo de memoria compartida similar a pthreads. Múltiples threads comparten la misma memoria lineal. La sincronización pasa a través de operaciones atómicas sobre esa memoria.\n\n```c\n// Compilar con: emcc -pthread -s SHARED_MEMORY=1 -s PTHREAD_POOL_SIZE=8\n#include <pthread.h>\n#include <stdatomic.h>\n\n#define WIDTH 800\n#define HEIGHT 600\n#define NUM_SAMPLES 64\n\nstatic uint32_t framebuffer[WIDTH * HEIGHT];\nstatic atomic_int next_row;\nstatic atomic_int completed_rows;\n\nvoid* render_thread(void* arg) {\n while (1) {\n int row = atomic_fetch_add(&next_row, 1);\n if (row >= HEIGHT) break;\n\n for (int x = 0; x < WIDTH; x++) {\n float r = 0, g = 0, b = 0;\n for (int s = 0; s < NUM_SAMPLES; s++) {\n Ray ray = camera_ray(x, row, s);\n Vec3 color = trace(ray, scene, 0);\n r += color.x; g += color.y; b += color.z;\n }\n r /= NUM_SAMPLES; g /= NUM_SAMPLES; b /= NUM_SAMPLES;\n framebuffer[row * WIDTH + x] = pack_rgba(r, g, b, 1.0f);\n }\n atomic_fetch_add(&completed_rows, 1);\n }\n return NULL;\n}\n```"},{"heading":"Integración con el browser: Workers + SharedArrayBuffer","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#integracin-con-el-browser-workers-sharedarraybuffer","content":"En el browser, cada thread de WASM corre en un Web Worker:\n\n```javascript\nconst memory = new WebAssembly.Memory({\n initial: 256, maximum: 1024, shared: true\n});\n\nconst numThreads = navigator.hardwareConcurrency || 4;\n\nfor (let i = 0; i < numThreads; i++) {\n const worker = new Worker('worker.js');\n worker.postMessage({\n type: 'init', wasmBytes, memory,\n threadId: i, totalThreads: numThreads\n });\n}\n\n// Leer el framebuffer y renderizar al canvas\nconst canvas = document.getElementById('canvas');\nconst ctx = canvas.getContext('2d');\nconst imageData = ctx.createImageData(800, 600);\n\nfunction renderFrame() {\n const pixels = new Uint8ClampedArray(memory.buffer, 0, 800 * 600 * 4);\n imageData.data.set(pixels);\n ctx.putImageData(imageData, 0, 0);\n requestAnimationFrame(renderFrame);\n}\nrenderFrame();\n```\n\nEl requisito crítico: tu página debe configurar headers de seguridad para que ` SharedArrayBuffer ` funcione:\n\n```\nCross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: require-corp\n```\n\nSin estos headers, ` SharedArrayBuffer ` se deshabilita y tu memoria compartida no va a funcionar. Este es el gotcha de deploy más común."},{"heading":"Performance: los números reales","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#performance-los-nmeros-reales","content":"Los benchmarks del ray tracer revelan resultados significativos. La escena es una Cornell box con 4 esferas, 64 samples por pixel, 800x600:\n\n```\nC nativo (gcc -O3, 8 threads): 1.240ms\nWASM threads (Chrome, 8 workers): 1.890ms (1.52x nativo)\nWASM threads (Firefox, 8 workers): 2.100ms (1.69x nativo)\nWASM single-thread (Chrome): 9.450ms (7.62x nativo)\nJavaScript (optimizado a mano, 8 workers): 14.200ms (11.45x nativo)\n```\n\nWASM threads logra 52-66% del rendimiento nativo. El scaling es casi lineal hasta el conteo de cores físicos:\n\n```\n1 thread: 9.450ms\n2 threads: 4.780ms (1.98x speedup)\n4 threads: 2.410ms (3.92x speedup)\n8 threads: 1.890ms (5.00x speedup)\n```"},{"heading":"WASI threads fuera del browser","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#wasi-threads-fuera-del-browser","content":"La propuesta ` wasi-threads ` trae el mismo modelo a runtimes WASM del lado servidor:\n\n```bash\nclang --target=wasm32-wasi-threads \\\n -pthread -matomics -mbulk-memory \\\n -Wl,--import-memory,--shared-memory,--max-memory=67108864 \\\n -o ray_tracer.wasm ray_tracer.c\n\nwasmtime run --wasi threads ray_tracer.wasm\n```\n\nEn Rust, el target ` wasm32-wasi-threads ` es experimental pero funcional:\n\n```rust\nuse std::sync::atomic::{AtomicI32, Ordering};\nuse std::sync::Arc;\n\nfn main() {\n let counter = Arc::new(AtomicI32::new(0));\n let mut handles = vec![];\n\n for _ in 0..8 {\n let counter = Arc::clone(&counter);\n let handle = std::thread::spawn(move || {\n for _ in 0..1000 {\n counter.fetch_add(1, Ordering::Relaxed);\n }\n });\n handles.push(handle);\n }\n\n for handle in handles {\n handle.join().unwrap();\n }\n assert_eq!(counter.load(Ordering::SeqCst), 8000);\n}\n```"},{"heading":"Primitivas de sincronización","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#primitivas-de-sincronizacin","content":"```c\ntypedef struct { _Atomic int locked; } WasmMutex;\n\nvoid wasm_mutex_lock(WasmMutex* m) {\n while (1) {\n int expected = 0;\n if (atomic_compare_exchange_weak(&m->locked, &expected, 1)) return;\n __builtin_wasm_memory_atomic_wait32(&m->locked, 1, -1);\n }\n}\n\nvoid wasm_mutex_unlock(WasmMutex* m) {\n atomic_store(&m->locked, 0);\n __builtin_wasm_memory_atomic_notify(&m->locked, 1);\n}\n```\n\nEl par ` wait32/notify ` es crucial. Sin ellos, usarías un spin-lock que quema ciclos de CPU. ` wait32 ` le dice al runtime \"dormí este thread hasta que el valor en esta dirección de memoria cambie.\""},{"heading":"Dónde importa esto","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#dnde-importa-esto","content":"WASM threads desbloquean workloads que antes eran impracticables en el browser:\n\n- **Procesamiento de imagen/video**: Operaciones paralelas de pixels\n- **Computación científica**: Simulaciones Monte Carlo, operaciones de matrices\n- **Motores de juegos**: Simulación de física en threads separados\n- **Compresión**: Compresión de bloques paralela (zstd, brotli)\n- **Inferencia de ML**: Multiplicación de matrices paralela para modelos chicos\n\nWASM threads no son un reemplazo completo del threading nativo. Son una aproximación suficientemente buena que trae paralelismo real a ambientes sandboxeados. Para los workloads que se benefician, y el speedup de 5x del ray tracer con 8 threads prueba que existen, eso alcanza para cambiar lo que es posible."},{"heading":"Preguntas frecuentes","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#questions","content":""},{"heading":"¿Qué son los WASI threads?","level":3,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#question-1","content":"WASI threads es una propuesta que agrega creación de threads y soporte de shared memory al WebAssembly System Interface. Permite que módulos WASM creen threads que comparten la misma memoria lineal, habilitando computación paralela real."},{"heading":"¿Puedo usar WASM threads en el browser?","level":3,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#question-2","content":"Sí, via SharedArrayBuffer y Web Workers. Cada worker carga el mismo módulo WASM con memoria compartida. Los headers COOP y COEP deben estar seteados."},{"heading":"¿Cómo se compara el rendimiento de WASM threads con nativo?","level":3,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#question-3","content":"En workloads compute-bound, WASM threads logran 60-80% del rendimiento nativo de threads. El overhead viene del bounds checking en acceso a memoria compartida y el costo de creación de workers del browser."},{"heading":"Tips","level":2,"url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#article-tips","content":"1. **Tip:** Utilizar ` memory.atomic.wait32 ` y ` memory.atomic.notify ` para sincronización de threads en vez de spin-locks. Los spin-locks queman ciclos de CPU; wait/notify cede al scheduler.\n2. **Tip:** Siempre compilá con ` -pthread -matomics -mbulk-memory ` cuando apuntés a WASM threads desde C/C++. Si falta algún flag, el binario cae silenciosamente a comportamiento single-threaded.\n3. **Tip:** Configurar los headers ` Cross-Origin-Opener-Policy: same-origin ` y ` Cross-Origin-Embedder-Policy: require-corp ` en tu página HTML. Sin estos, los browsers deshabilitan ` SharedArrayBuffer `.\n4. **Tip:** Perfilar con ` performance.measureUserAgentSpecificMemory() ` para trackear uso de memoria por thread. Los profilers de heap estándar no distinguen memoria shared vs private en WASM.\n\n- wasi\n- wasm\n- threads\n- shared-memory\n- atomics\n- parallel-computing\n- webassembly\n- ray-tracer\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)"}],"links":[{"text":"English","url":"https://lucioduran.com/blog/wasi-threads-shared-memory-parallel-wasm"},{"text":"Volver al Blog","url":"https://lucioduran.com/es/blog"}],"structuredData":[{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","@id":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm#article","mainEntityOfPage":{"@type":"WebPage","@id":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm"},"headline":"WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly","description":"Shared memory en WebAssembly, atomics, computación paralela, SharedArrayBuffer, explorando WASM threads a través de una implementación de ray tracer para separar la realidad de la exageración.","datePublished":"2025-10-31","author":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"publisher":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"image":"https://lucioduran.com/favicons/og-default.png","url":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm","inLanguage":"es","isPartOf":{"@id":"https://lucioduran.com/blog#blog"},"articleSection":"WebAssembly","keywords":"wasi, wasm, threads, shared-memory, atomics, parallel-computing, webassembly, ray-tracer","wordCount":683,"timeRequired":"PT4M","workTranslation":[{"@type":"BlogPosting","inLanguage":"en","url":"https://lucioduran.com/blog/wasi-threads-shared-memory-parallel-wasm"}]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https://lucioduran.com/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://lucioduran.com/es/blog"},{"@type":"ListItem","position":3,"name":"WASI Threads: El Paralelismo con Memoria Compartida Llega a WebAssembly","item":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm"}]},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"¿Qué son los WASI threads?","acceptedAnswer":{"@type":"Answer","text":"WASI threads es una propuesta que agrega creación de threads y soporte de shared memory al WebAssembly System Interface. Permite que módulos WASM creen threads que comparten la misma memoria lineal, habilitando computación paralela real."}},{"@type":"Question","name":"¿Puedo usar WASM threads en el browser?","acceptedAnswer":{"@type":"Answer","text":"Sí, via SharedArrayBuffer y Web Workers. Cada worker carga el mismo módulo WASM con memoria compartida. Los headers COOP y COEP deben estar seteados."}},{"@type":"Question","name":"¿Cómo se compara el rendimiento de WASM threads con nativo?","acceptedAnswer":{"@type":"Answer","text":"En workloads compute-bound, WASM threads logran 60-80% del rendimiento nativo de threads. El overhead viene del bounds checking en acceso a memoria compartida y el costo de creación de workers del browser."}}]}]}],"contentHash":"c93941b9892d2bf549747ddb6981410ab7cf53ab1128a561d376da00799f4bec","provenance":{"method":"Deterministic serialization of the server-rendered main element","source":"https://lucioduran.com/es/blog/wasi-threads-shared-memory-parallel-wasm","hashAlgorithm":"sha256","hashScope":"JSON document fields before contentHash and provenance","sourceHTMLBytes":49848,"contentBytes":7262}}
