optimize-bevy-game
Use when a Bevy game stutters, drops frames, loads slowly, or ships a large binary or wasm — measure with diagnostics and Tracy/Chrome traces first, then fix change detection, system parallelism, batc
SKILL.mdskills/game/optimize-bevy-game/SKILL.md
GitHubOptimize Bevy Game
Bevy 0.20. Rationale per rule: optimization-patterns.md. Versions: stack-versions. Principle: measure before optimizing.
1. Audit current state (change nothing)
cat .claude/stack-profile.md 2>/dev/null # hosting/web target, task_runner
grep -nE '^\[profile|opt-level|lto|codegen-units|strip|panic' Cargo.toml
grep -nE 'trace|tracing|dynamic_linking|"debug"' Cargo.toml
grep -rnE 'FrameTimeDiagnosticsPlugin|LogDiagnosticsPlugin|FpsOverlay' src/
grep -rnE 'Vec::new\(\)|collect::<Vec|format!\(|\.clone\(\)' src/ | head -20 # per-frame allocation suspects
grep -rnE 'iter_mut\(\)|&mut [A-Z]' src/ | head # mutable access that marks change
ls -l target/release/* 2>/dev/null | head -3; ls -l dist/*.wasm 2>/dev/null
State the symptom as a number before touching code: frame time in ms (not FPS), load time in s, binary or wasm size in MB. "It feels slow" is not a symptom.
2. Decide what to do
- No measurement yet → step 5 (measure). Stop there until the numbers exist.
- Measured, a system or plugin dominates → fix that one; re-measure.
- Size or startup problem only → release/wasm profile rules, no code changes.
- Numbers already meet the target (say a 16.6 ms frame, a wasm under budget) → "already in place", stop.
3. Detect track
- CPU-bound (a system tops the trace): change detection, parallel iteration, allocation, scheduling.
- GPU-bound (frame time tracks resolution or sprite/mesh count, systems are short): batching, atlases, fewer materials, lower resolution.
- Load / size: asset processing (manage-bevy-assets), release profile, wasm size.
4. Install only what's missing
Profiling needs a Tracy viewer matched to the client library version, or nothing (Chrome traces open in ui.perfetto.dev):
cargo tree --features bevy/trace_tracy | grep tracy # read the tracy-client version, then match the Tracy UI to it
Tracy UI: official Windows binaries, third-party macOS/Linux builds (tracy-builds), or a package manager. wasm size tools: wasm-bindgen-cli (same version as the crate) and optionally Binaryen wasm-opt.
5. Measure first
cargo run --release --features bevy/trace_chrome # writes trace-*.json; open in https://ui.perfetto.dev
cargo run --release --features bevy/trace_tracy,bevy/debug # live in Tracy; `debug` gives Bevy systems readable names
Quick numbers without a profiler: add FrameTimeDiagnosticsPlugin::default() and LogDiagnosticsPlugin::default() to the app (dev builds only). Always profile --release; dev builds mislead.
Read the trace: find the longest system span per frame and what it waits on. Write down: system name, ms per frame, the target.
6. Fix, one change at a time
Apply the first matching rule from optimization-patterns.md, in this order:
- Skip work:
Changed<T>/Added<T>, run conditions,set_if_neq. - Parallelism: disjoint queries so the scheduler can overlap systems;
par_iter_mutfor large heavy loops. - Allocation: reuse
Local<Vec<_>>,spawn_batch, noformat!orcollectper frame. - Rendering: texture atlases, shared materials, fewer unique handles; see GPU rule.
- Build profile:
lto,codegen-units,panic = "abort"only when measured. - Web size:
wasm-releaseprofile,wasm-bindgen, optionalwasm-opt.
Canonical release profile (desktop):
[profile.release]
codegen-units = 1
lto = "thin"
Web:
[profile.wasm-release]
inherits = "release"
opt-level = "s"
strip = "symbols"
7. Verify
Repeat the exact measurement from step 5 and compare:
cargo run --release --features bevy/trace_chrome # same scene, same machine, same duration
cargo build --profile wasm-release --target wasm32-unknown-unknown && ls -l target/wasm32-unknown-unknown/wasm-release/*.wasm
Expected: the target number is met, or the change is reverted. Keep a one-line before/after in the PR description. Run cargo nextest run to confirm behavior did not change.
Related: structure-bevy-app (sets and ordering), test-bevy-systems (ambiguity check).