Tree-shaking, the horticulturally misguided algorithm (2023)
Tree-shaking vs. Dead Code Elimination (DCE)
- Strong debate over terminology. Some argue “tree-shaking” is a confusing misnomer and that “dead code elimination” or “reachability analysis” are clearer, long‑established terms.
- Others defend “tree-shaking” as evocative, widely adopted (especially in JS), and semantically distinct: often used for bundler‑level, inter‑module pruning based on dependency graphs, while “DCE” is used for compiler/engine‑level, often intra‑function optimizations.
- Historical notes: early “treeshakers” in Lisp (and possibly Smalltalk) operated on whole images, removing unused code and data, not just functions. Some argue this broader scope justifies a distinct term.
- Several commenters insist the operations are conceptually the same; others maintain that granularity and tooling differences justify two names.
Wasm Code Size and Practical Optimization
- Consensus that Wasm often suffers from large code size, problematic for initial page load and serverless cold starts.
- Techniques reported to reduce size (mostly in Rust/Wasm):
- Avoid floats, HashMaps, and strings when possible; use fixed point and vectors.
- Minimize generic type diversity to avoid monomorphization bloat.
- Use small allocators and strict size‑oriented compiler settings (e.g.,
opt-level="z", LTO, single codegen unit). - Post-process with
wasm-optand serve with Brotli compression.
- Some think shrinking from ~700KB to ~400KB is only marginally useful on the web; others see it as an important counterexample to perceptions that Wasm apps are inevitably bloated.
- Rust’s formatting/
dbg!and standard library can inject surprising size overhead. WasmGC is seen as a way to cut runtime/allocator bulk, with current best results cited for Java/Kotlin.
Dynamic Linking and Shared Runtimes
- Proposed long‑term fix: treat language runtimes as dynamically linked Wasm modules shared across apps.
- Example: a single Pyodide runtime can be shared across many serverless workers.
- Vision: browsers (or platforms) pre‑load popular runtimes/libraries so individual apps don’t ship them each time.
- Concerns raised:
- Cache partitioning and fingerprinting/privacy issues.
- Version explosion and ABI stability; would require strong backward compatibility or curated, limited sets of versions.
- Governance questions over which runtimes get “blessed” and preloaded.
- Ideas floated: profile‑guided tree‑shaking plus on‑demand downloading of rarely used code, but risk of missing rare paths is noted.
Wasm, DOM Access, and GUI Models
- Current reality: DOM and Web APIs are exposed to JS, so Wasm typically calls through JS “glue.” GC‑based references (WasmGC, component model) are expected to make direct DOM interaction more feasible.
- Some argue that bypassing DOM/JS to render entirely via canvas/WebGL/WebGPU (for “native‑style” apps) is attractive; others counter this sacrifices accessibility and browser‑provided UI primitives, effectively “building a browser inside the browser.”
- There is disagreement over whether Wasm should mainly supplement JS (e.g., heavy compute, workers) or be a full replacement for JS in front‑end development.
Wider Role and Design of Wasm
- One camp sees Wasm as a deliberately minimal, secure, capability‑based “MVP” ISA, expected to grow features (GC, better host bindings).
- Another camp finds it underpowered compared to classic VMs (no built‑in GC/stdlib or trivial DOM hooks), questioning its value for general web apps and some edge/FaaS scenarios.
- Despite skepticism, multiple real uses are cited (games, RL libraries, map/earth viewers, Blazor, Flutter font/icon shaking), and some languages (e.g., OCaml, Zig) are viewed as promising for ultra‑small Wasm outputs.