WebAssembly Performance Analysis in d8
Reproduce, profile, and analyze Wasm performance using the V8 developer shell
(d8).
1. Reproduction and Establishing a Baseline
- Build Configurations:
- CRITICAL: Always use a
release build (e.g., out/x64.release/d8)
for benchmarking.
- Use
optdebug (e.g., out/x64.optdebug/d8) for disassembling/debugging
(preserves symbols).
- Measurement Metrics:
- Wall time: Measure execution time (e.g., JS
console.time()).
- LLM Tip (Statistical Rigor & Warmup): Run 3-5 times; take the
median/average. Ensure code runs in a loop to trigger Turboshaft tier-up
(warmup) before measuring.
- Resource/CPU: Use
/usr/bin/time -v (Wall time, memory) and
perf stat -d (cycles, instructions, IPC, branch misses).
- LLM Tip (perf Fallback): If
perf fails due to permissions (e.g.
kernel.perf_event_paranoid), notify the user to adjust settings or
switch to a PMU-enabled environment (gLinux/Cloudtop). Fall back to
d8 --prof if needed.
- GC Overhead: Use
--trace-gc to trace garbage collection pauses,
especially if WasmGC is used.
- Tier Isolation: Compare performance between execution tiers to understand
the optimization effect.
- Liftoff (Baseline):
d8 --liftoff-only script.js
- Turboshaft (Optimized):
d8 --no-liftoff script.js
- Note:
--no-liftoff disables speculative inlining since it skips
Liftoff execution and thus doesn't collect feedback.
2. Hotspot Identification
Find where time is spent, what the hottest functions, loops, blocks, or
instructions are, so we focus on that:
- Linux Perf: Run
./tools/profiling/linux-perf-d8.py to get a profile with
JIT symbols resolved, then analyze with perf report.
- V8 Profiler: Run
d8 --prof script.js and analyze v8.log with
./tools/linux-tick-processor.
- Categorize Hotspots: Wasm user code, JS code, V8 C++
Runtime/GC/Compilation, or JS/Wasm boundary (wrappers).
3. Deep Dive Analysis
Compilation Overhead
- Identify Slow to Compile Functions: Use
d8 --trace-wasm-compilation-times and d8 --turbo-stats-wasm.
- Inspect Bytecode: Build
wami (tools/dev/gm.py x64.release wami) and
disassemble: out/x64.release/wami --single-wat=<func_index> <path_to_wasm>
Wasm Binary Quality & Toolchain
Unoptimized Wasm binary patterns can hurt V8 compilation and execution.
- Ask the user if source code (C++/Rust) is available.
- Check for: huge functions, excessive locals, many branches, or missed static
optimizations.
- Ensure binary is a release build (compiled with
-O3/-Os).
Execution Performance & Optimization (Deep Dives)
Perform deep dives on hot functions:
- Turboshaft IR Traces: Run
d8 --trace-turbo --trace-turbo-filter=<func_name>.
- Context Window: To keep the context windows clean use
jq
programmatically:
- List phases:
jq '.phases[].name' turbo-*.json
- Count nodes:
jq '.phases[] | {name: .name, node_count: (if (.data | type) == "object" and .data.nodes then (.data.nodes | length) else 0 end)}' turbo-*.json
- Find ops:
jq '.phases[] | select(.name == "TurboshaftTypeAssertionsPhase") | select((.data | type) == "object" and .data.nodes) | .data.nodes[] | select(.title | contains("BoundsCheck"))' turbo-*.json
- Assembly Profiling: Run
perf annotate -i file.perf.data.jitted --stdio
to map hot instructions to bytecode.
- Instruction Skid: Account for cycle misattribution; inspect surrounding
instructions and data dependencies.
- Disassembly & Comments: Run
out/x64.optdebug/d8 --print-wasm-code-function-index=<idx> --code-comments.
- LLM Tip: Redirect disassembly output to a file (
> disasm.txt) to avoid
flooding the terminal.
- Optimization & Tracing Flags:
- Inlining:
--trace-wasm-inlining, --trace-turbo-inlining
- Loop Peeling and Unrolling: Enable/disable
--wasm-loop-peeling,
--wasm-loop-unrolling to see an effect of those optimizations.
- Other Optimizations:
--turboshaft-trace-load-elimination,
--turboshaft-trace-peeling, --turboshaft-trace-unrolling
- Typing:
--trace-wasm-typer
- Inlining & Tiering Budgets: Scalability tuning flags to adjust
optimizations:
- Tiering up earlier or later:
--wasm-tiering-budget=<value>.
- Inline more or less aggressively:
--wasm-inlining-budget=<value>.
- V8 Flag Discovery: Search for context-specific flags using
d8 --help | grep -i <keyword> or by looking up definitions in
src/flags/flag-definitions.h and via grep. Refer to v8-commands skill
for general usage.
4. Synthesis and Reporting
Provide a clear report summarizing:
- Hottest Functions: Contribution and compilation tier (Liftoff vs
Turboshaft).
- Inlining Status: Report Wasm-to-Wasm and JS/Wasm wrapper and body
inlining.
- Wasm Input Binary Properties: Release vs debug, missed static
optimizations, very large functions, or otherwise noteworthy code patterns.
- Disassembly & Assembly Hotspots: Highlight hot instructions and map them
to Wasm bytecode.
- Turboshaft Optimization: Key phases affecting the CFG and any failed
optimizations.
- Code Skeleton: Provide a simplified snippet of the hot block/loop at the
most useful level (source, bytecode, IR, or machine code).
5. Experimentation & Verification
Only proceed to this step after your initial report and explicit approval by the
user.
- Ablation Studies: Toggle optimizations to measure wall-time impact (e.g.
--no-wasm-loop-unrolling, --no-turboshaft-wasm-load-elimination,
--no-wasm-inlining, --no-turbo-inline-js-wasm-calls).
- LLM Tip: Present results in a Before vs. After table.
- Wasm Binary/Static Optimization: Use
wasm-opt -O3 (or -Os) if
available on PATH, or ask the user to rebuild with different flags.
- Hypotheses: Align on potential optimization opportunities with the user
before implementing fixes.
1---2name: wasm-d8-perf3description: Use this skill to reproduce, profile, or analyze WebAssembly (Wasm) execution performance using d8 shell.4---56# WebAssembly Performance Analysis in d878Reproduce, profile, and analyze Wasm performance using the V8 developer shell9(`d8`).1011## 1. Reproduction and Establishing a Baseline1213- **Build Configurations**:14 - **CRITICAL**: Always use a **`release`** build (e.g., `out/x64.release/d8`)15 for benchmarking.16 - Use **`optdebug`** (e.g., `out/x64.optdebug/d8`) for disassembling/debugging17 (preserves symbols).18- **Measurement Metrics**:19 - **Wall time**: Measure execution time (e.g., JS `console.time()`).20 - *LLM Tip (Statistical Rigor & Warmup)*: Run 3-5 times; take the21 median/average. Ensure code runs in a loop to trigger Turboshaft tier-up22 (warmup) before measuring.23 - **Resource/CPU**: Use `/usr/bin/time -v` (Wall time, memory) and24 `perf stat -d` (cycles, instructions, IPC, branch misses).25 - *LLM Tip (perf Fallback)*: If `perf` fails due to permissions (e.g.26 `kernel.perf_event_paranoid`), notify the user to adjust settings or27 switch to a PMU-enabled environment (gLinux/Cloudtop). Fall back to28 `d8 --prof` if needed.29 - **GC Overhead**: Use `--trace-gc` to trace garbage collection pauses,30 especially if WasmGC is used.31- **Tier Isolation**: Compare performance between execution tiers to understand32 the optimization effect.33 - Liftoff (Baseline): `d8 --liftoff-only script.js`34 - Turboshaft (Optimized): `d8 --no-liftoff script.js`35 - *Note*: `--no-liftoff` disables speculative inlining since it skips36 Liftoff execution and thus doesn't collect feedback.3738## 2. Hotspot Identification3940Find where time is spent, what the hottest functions, loops, blocks, or41instructions are, so we focus on that:4243- **Linux Perf**: Run `./tools/profiling/linux-perf-d8.py` to get a profile with44 JIT symbols resolved, then analyze with `perf report`.45- **V8 Profiler**: Run `d8 --prof script.js` and analyze `v8.log` with46 `./tools/linux-tick-processor`.47- **Categorize Hotspots**: Wasm user code, JS code, V8 C++48 Runtime/GC/Compilation, or JS/Wasm boundary (wrappers).4950## 3. Deep Dive Analysis5152### Compilation Overhead5354- **Identify Slow to Compile Functions**: Use55 `d8 --trace-wasm-compilation-times` and `d8 --turbo-stats-wasm`.56- **Inspect Bytecode**: Build `wami` (`tools/dev/gm.py x64.release wami`) and57 disassemble: `out/x64.release/wami --single-wat=<func_index> <path_to_wasm>`5859### Wasm Binary Quality & Toolchain6061Unoptimized Wasm binary patterns can hurt V8 compilation and execution.6263- Ask the user if source code (C++/Rust) is available.64- Check for: huge functions, excessive locals, many branches, or missed static65 optimizations.66- Ensure binary is a release build (compiled with `-O3`/`-Os`).6768### Execution Performance & Optimization (Deep Dives)6970Perform deep dives on hot functions:7172- **Turboshaft IR Traces**: Run73 `d8 --trace-turbo --trace-turbo-filter=<func_name>`.74 - *Context Window*: To keep the context windows clean use `jq`75 programmatically:76 - List phases: `jq '.phases[].name' turbo-*.json`77 - Count nodes:78 `jq '.phases[] | {name: .name, node_count: (if (.data | type) == "object" and .data.nodes then (.data.nodes | length) else 0 end)}' turbo-*.json`79 - Find ops:80 `jq '.phases[] | select(.name == "TurboshaftTypeAssertionsPhase") | select((.data | type) == "object" and .data.nodes) | .data.nodes[] | select(.title | contains("BoundsCheck"))' turbo-*.json`81- **Assembly Profiling**: Run `perf annotate -i file.perf.data.jitted --stdio`82 to map hot instructions to bytecode.83 - *Instruction Skid*: Account for cycle misattribution; inspect surrounding84 instructions and data dependencies.85- **Disassembly & Comments**: Run86 `out/x64.optdebug/d8 --print-wasm-code-function-index=<idx> --code-comments`.87 - *LLM Tip*: Redirect disassembly output to a file (`> disasm.txt`) to avoid88 flooding the terminal.89- **Optimization & Tracing Flags**:90 - Inlining: `--trace-wasm-inlining`, `--trace-turbo-inlining`91 - Loop Peeling and Unrolling: Enable/disable `--wasm-loop-peeling`,92 `--wasm-loop-unrolling` to see an effect of those optimizations.93 - Other Optimizations: `--turboshaft-trace-load-elimination`,94 `--turboshaft-trace-peeling`, `--turboshaft-trace-unrolling`95 - Typing: `--trace-wasm-typer`96- **Inlining & Tiering Budgets**: Scalability tuning flags to adjust97 optimizations:98 - Tiering up earlier or later: `--wasm-tiering-budget=<value>`.99 - Inline more or less aggressively: `--wasm-inlining-budget=<value>`.100- **V8 Flag Discovery**: Search for context-specific flags using101 `d8 --help | grep -i <keyword>` or by looking up definitions in102 `src/flags/flag-definitions.h` and via `grep`. Refer to `v8-commands` skill103 for general usage.104105## 4. Synthesis and Reporting106107Provide a clear report summarizing:1081091. **Hottest Functions**: Contribution and compilation tier (Liftoff vs110 Turboshaft).1112. **Inlining Status**: Report Wasm-to-Wasm and JS/Wasm wrapper and body112 inlining.1133. **Wasm Input Binary Properties**: Release vs debug, missed static114 optimizations, very large functions, or otherwise noteworthy code patterns.1154. **Disassembly & Assembly Hotspots**: Highlight hot instructions and map them116 to Wasm bytecode.1175. **Turboshaft Optimization**: Key phases affecting the CFG and any failed118 optimizations.1196. **Code Skeleton**: Provide a simplified snippet of the hot block/loop at the120 most useful level (source, bytecode, IR, or machine code).121122## 5. Experimentation & Verification123124Only proceed to this step after your initial report and explicit approval by the125user.126127- **Ablation Studies**: Toggle optimizations to measure wall-time impact (e.g.128 `--no-wasm-loop-unrolling`, `--no-turboshaft-wasm-load-elimination`,129 `--no-wasm-inlining`, `--no-turbo-inline-js-wasm-calls`).130 - *LLM Tip*: Present results in a **Before vs. After table**.131- **Wasm Binary/Static Optimization**: Use `wasm-opt -O3` (or `-Os`) if132 available on `PATH`, or ask the user to rebuild with different flags.133- **Hypotheses**: Align on potential optimization opportunities with the user134 before implementing fixes.