.agents/skills/rspack-perf-valgrind-goal/SKILL.md
Use this for Rspack performance work where success is judged by the Callgrind instruction count of an exact benchmark stage measured locally in a pinned native-architecture Docker environment. Build the existing Rust benchmark target with ordinary Cargo, execute the selected binary directly under Valgrind, and decide only from local Callgrind profiles. Do not run a CodSpeed CLI, use a token, upload results, read CodSpeed PR comments, or wait for GitHub Actions.
The agent owns the loop. After the user gives the target benchmark stage, threshold, and scope, continue until local Valgrind confirms the target and correctness validation passes, a real blocker prevents progress, or the configured round limit is reached.
$rspack-perf to guide optimization strategy before changing code.instruction_count. Benchmark harness labels, cloud percentages, and wall time are not performance evidence for this workflow./goal, retain the original target across resumes. Do not redefine success around partial progress.Use scripts/run_local_valgrind.sh from this skill. It builds a reusable native-architecture image containing the repository's pinned Rust toolchain and Debian's standard Valgrind package. The helper mounts source and canonical fixtures read-only, stores build caches in Docker volumes keyed by checkout path, image ID, and native platform, builds with ordinary Cargo, executes only the selected benchmark binary under Callgrind, captures raw logs and profiles, and records an environment manifest.
For persistent-cache benchmark filters, the helper copies the read-only fixtures into ephemeral writable container storage before execution because those benchmarks create temporary workspaces beneath RSPACK_BENCHCASES_DIR. The copy preserves fixture symlinks and is discarded with the container; never make the canonical host fixture directory writable.
The helper passes the repository's existing --cfg codspeed compile-time switch to ordinary cargo build so the benchmark adapter exposes its Valgrind client-request boundaries. This is only a source configuration name: no CodSpeed executable, service, token, API, upload, PR comment, or benchmark result participates in the workflow. Valgrind starts instrumentation at the selected benchmark boundary, and run-*.instructions plus the local Callgrind profiles are the only performance source of truth.
Verify Docker before preparing fixtures or building the measurement image:
command -v docker
docker version
docker info
docker compose version
docker run --rm hello-world
If Docker is missing or the engine is unavailable, install and validate it before continuing. When the local task history is available, read task 019f7e27-50ba-7ac1-8ab4-3cdc868818fe (安装 Docker 并运行 Valgrind) and follow its tested installation flow. Do not replace the Docker measurement environment with host-side Valgrind.
Apply these installation requirements even when that task cannot be read:
PATH, add its supported CLI directory to the shell configuration, start a new shell, and re-run the verification commands above.docker run --rm hello-world to verify image pulling, credentials, networking, and container execution rather than accepting an installed application as sufficient evidence.SIGKILL with the default 8 GiB allocation. If that happens, increase Docker memory, restart the engine, preserve the Docker volumes, and resume the cached build.hello-world verification.From the optimization checkout, initialize the environment once:
SKILL_DIR="<absolute path to .agents/skills/rspack-perf-valgrind-goal>"
"$SKILL_DIR/scripts/run_local_valgrind.sh" build-image
"$SKILL_DIR/scripts/run_local_valgrind.sh" prepare --repo "<optimization checkout>"
Prepare fixtures only once for a goal. Pass that exact fixture directory to both base and candidate measurements:
"$SKILL_DIR/scripts/run_local_valgrind.sh" measure \
--repo "<checkout to measure>" \
--fixtures "<optimization checkout>/.bench/rspack-benchcases" \
--bench "<benches or rspack_sources>" \
--filter "<exact benchmark filter>" \
--output "<absolute result directory>"
The helper defaults to two repetitions. Read each exact instruction count from run-*.instructions. If the stage differs by more than 0.5% between repetitions, run a third repetition with --repeat 3 and use the median. Keep raw logs and Callgrind profiles; do not copy a number manually without retaining its source artifact.
Establish a clean optimization checkout.
Establish the target.
benches or rspack_sources) and the narrowest filter that includes the stage.Freeze the local environment.
environment.txt.linux/arm64 on Apple Silicon and Arm hosts, or linux/amd64 on x86-64 hosts. Valgrind must not run through cross-architecture QEMU emulation.GLIBC_TUNABLES, allocator settings, and measurement mode unchanged.Create an immutable base measurement.
/tmp.run-*.instructions, confirm each corresponding log ran the intended filter, and apply the repetition rule above.Create or identify the fixed progress report.
Run these steps in order for every round.
Modify code locally.
Verify correctness locally.
Run a correctness-focused independent review.
Commit the candidate snapshot.
perf: ....Measure the candidate locally.
(comparison - candidate) / comparison * 100.Decide whether to retain the round.
Push and report the decided state.
Handle available code review comments.
run-*.instructions file. It is the sum of Callgrind totals: values produced while the selected benchmark boundary was instrumented.Keep one fixed PR comment, or the equivalent task report when there is no PR:
## Local Valgrind Optimization Log
Target: `<exact measured stage>` >= `<threshold>` improvement
Scope: `<requested scope>`
Environment: `<image id>`, `<native Docker platform>`, `<benchmark target> <filter>`
Base: `<sha>` at `<instruction count>`
Current status: `<running|passed|failed|blocked>`
Latest head: `<sha>`
| Round | Commit | Change | Local Valgrind | Decision | Correctness |
| ----- | ------- | ----------- | ---------------------------- | --------------------- | ----------- |
| 1 | `<sha>` | `<summary>` | `<base -> candidate; delta>` | `<retained/reverted>` | `<summary>` |
Update this report rather than duplicating it. Keep entries concise and include links or paths to raw local logs.
Keep updates short and decision-oriented: