Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.7 KiB
id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
| id | title | status | type | domain | scope | priority | depends | blocks | related | created | updated | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0072d | gamedev — WASM build pipeline + size budget | pendiente | feature |
|
multi-app | alta |
|
2026-05-10 | 2026-05-17 |
|
Objetivo
Pipeline reproducible de build WASM con presupuestos de tamaño estrictos y herramientas de auditoria. WASM es la plataforma prioritaria por la integracion crypto (sub-issues 0072e, 0072f), y el peso del bundle es el factor de retencion mas critico (cada 100KB extra = ~1% de drop-off en navegador).
Presupuestos
| Artefacto | Limite duro | Limite blando |
|---|---|---|
*.wasm raw |
5 MB | 4 MB |
*.wasm.gz (gzip -9) |
2 MB | 1.5 MB |
*.wasm.br (brotli -11) |
1.5 MB | 1.2 MB |
*.js (loader) gzip |
50 KB | 30 KB |
*.html (shell) |
10 KB | 5 KB |
Bundle assets .pak |
5 MB | 3 MB |
Total objetivo: < 4 MB descargados (wasm.br + js.gz + assets.gz) para "first paintable scene".
Pipeline
bash/functions/pipelines/build_wasm_cpp_pipelines.sh:
#!/usr/bin/env bash
# build_wasm <app_name> [--release|--debug] [--no-budget-check]
set -euo pipefail
APP="$1"; shift
MODE="${1:-release}"
SRC_DIR="cpp/apps/$APP"
BUILD_DIR="build/wasm/$APP"
# 1. emsdk
[ -d emsdk ] || git clone https://github.com/emscripten-core/emsdk
(cd emsdk && ./emsdk install latest && ./emsdk activate latest)
source emsdk/emsdk_env.sh
# 2. cmake
emcmake cmake -B "$BUILD_DIR" -S "$SRC_DIR" \
-DCMAKE_BUILD_TYPE=$([ "$MODE" = "release" ] && echo MinSizeRel || echo Debug)
cmake --build "$BUILD_DIR" -j
# 3. compress
WASM="$BUILD_DIR/$APP.wasm"
gzip -9 -k "$WASM"
brotli -q 11 -k "$WASM"
# 4. report
echo "── Sizes ──"
ls -lah "$BUILD_DIR/$APP".{wasm,wasm.gz,wasm.br,js,html}
# 5. budget check
if [ "${1:-}" != "--no-budget-check" ]; then
bash bash/functions/gamedev/wasm_size_budget_check.sh "$BUILD_DIR" "$APP"
fi
Funcion de auditoria
bash/functions/gamedev/wasm_size_budget_check.sh:
#!/usr/bin/env bash
# Falla con exit 1 si excede el budget duro
WASM_GZ="$BUILD_DIR/$APP.wasm.gz"
SIZE=$(stat -c%s "$WASM_GZ")
LIMIT=$((2 * 1024 * 1024))
if [ "$SIZE" -gt "$LIMIT" ]; then
echo "❌ $WASM_GZ = $SIZE bytes > $LIMIT (2 MB)"
exit 1
fi
echo "✓ $WASM_GZ within budget"
Banderas de compilacion (MinSizeRel)
if(EMSCRIPTEN)
target_compile_options(<target> PRIVATE
-Os # Optimize for size
-fno-exceptions # No C++ exceptions (huge win)
-fno-rtti # No RTTI
-ffunction-sections
-fdata-sections
)
target_link_options(<target> PRIVATE
-Os
-sASSERTIONS=0 # No runtime assertions in release
-sFILESYSTEM=0 # No emscripten filesystem (use fetch)
-sMINIMAL_RUNTIME=2 # Slim JS runtime
-sENVIRONMENT=web # Browser only, no node
-sUSE_WEBGL2=1
-sFULL_ES3=1
-sALLOW_MEMORY_GROWTH=1
-sINITIAL_MEMORY=33554432
-sSTACK_SIZE=1048576
--closure=1 # Closure compiler on JS glue
-Wl,--gc-sections
)
endif()
MINIMAL_RUNTIME=2 ahorra ~50KB de JS glue. FILESYSTEM=0 ahorra otros ~30KB. --closure=1 reduce JS otro ~30%.
Herramientas de auditoria
Cuando el budget se rompe, herramientas para encontrar el culpable:
twiggy(Rust tool, MIT) — analiza wasm y lista funciones por tamaño:twiggy top -n 50 build/wasm/engine_smoke.wasmwasm-objdump -h— secciones del binario.emcc --emit-symbol-map— mapa de simbolos para correlacionar con codigo C++.- Bloaty (Google, ASL2) — analisis size attribution.
Funcion: bash/functions/gamedev/wasm_size_audit.sh <wasm_path> — corre las 4 y produce reporte markdown.
Tecnicas de reduccion (cuando se exceda)
Documentar en cpp/GAMEDEV.md:
- No usar
<iostream>— ~80KB de runtime. Usarprintfo nada. - No usar
<filesystem>— pesado. SDL_RWops o emscripten fetch. std::function→ punteros a funcion cuando se pueda. ~5KB por instancia.std::regexprohibido — ~100KB. Usar parsers manuales ore2mini.- STL containers — usar pero con
-fno-exceptions.std::vectorOK,std::mapevitar (preferirstd::vector<pair>ordenado oflat_hash_mapmini). - Templates — instanciar pocas veces. Cada nueva instanciacion es codigo nuevo.
- Inlining —
-Osya lo balancea. No forzar__forceinline. - Vendor libs — auditar antes de añadir. Cada lib pasa por size review en su PR.
Streaming + caching
Para juegos mas grandes en el futuro:
--preload-fileempotra assets en.dataadyacente al wasm. Cargado de golpe.fetch()async para assets opcionales (niveles avanzados, musica).- Service Worker para cache offline (en sub-issue futuro, no urgente).
Integracion con CI
GitHub Actions / Gitea Actions workflow gamedev-wasm-budget.yml:
- Trigger: PR que toca
cpp/apps/engine_*ocpp/functions/gfx/sg_* - Build WASM
- Comprueba budgets
- Comenta tamaños en el PR
- Falla si rompe limite duro
Criterio de exito
- Pipeline
build_wasm_cpp_pipelines.shreproducible en Linux + Windows WSL. engine_smoke(de 0072a) pasa budget check.wasm_size_audit.shproduce reporte legible.- CI bloquea PRs que rompen el budget.
- Documentacion
cpp/GAMEDEV.mdactualizada con reglas de tamaño.
No-objetivos
- WebGPU (sokol_gfx WebGPU backend es alpha) — diferido.
- WASM SIMD — opcional, evaluar despues de medir hot paths.
- Multi-threading WASM (SharedArrayBuffer + COOP/COEP headers) — overkill, lo dejamos para juegos que lo pidan.