Repository navigation
chore(bench): report the shadow comparison instead of gating it #831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,23 +27,12 @@ cmd = [ | |
| ] | ||
| runs = 10 | ||
|
|
||
| # The gate: the same mise command line parsed by each framework, plus a binary that | ||
| # does everything except parse. The parse itself is the difference between the third | ||
| # number and the first — roughly two thirds of a small binary's instructions are the | ||
| # dynamic loader and libc starting up, and neither parser is responsible for those. | ||
| # The shadow benchmarks are deliberately *not* here. tak gates everything it finds in this | ||
| # file, and the mise shadow is a fixture that grows on purpose: teaching the derive command | ||
| # aliases added 91 names to it and 1.5% to the count, which the gate reported as a | ||
| # regression when it was the fixture getting bigger. A gate that fires for that teaches | ||
| # people to ignore it. | ||
| # | ||
| # `use -g node@20` rather than something exotic: it selects a subcommand, takes a | ||
| # global short, a switch and a value, which is what a real invocation looks like. The | ||
| # cost turns out to be near constant across shapes anyway, since there is no tree to | ||
| # build. | ||
| [bench.gate-baseline] | ||
| cmd = ["./target/release/parse-none", "use", "-g", "node@20"] | ||
| runs = 10 | ||
|
|
||
| [bench.gate-usage] | ||
| cmd = ["./target/release/parse-usage", "use", "-g", "node@20"] | ||
| runs = 10 | ||
|
|
||
| [bench.gate-clap] | ||
| cmd = ["./target/release/parse-clap", "use", "-g", "node@20"] | ||
| runs = 10 | ||
| # They are measured and reported by `mise run perf:shadow`, which the pull-request workflow | ||
| # appends to its comment. What is worth watching there is the ratio between the two | ||
| # frameworks, which is a property of the parsers rather than of the fixture. | ||
|
Comment on lines
+30
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Document why This comment explains why the shadow benchmarks are omitted, but it does not state that 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,69 @@ | ||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||
| # The shadow comparison: what parsing a mise-sized command line costs each framework. | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # Reported, never gated. The shadow is a fixture that grows on purpose — every property the | ||||||||||||||||||||||
| # derive learns to express adds to it — so comparing one commit's shadow against another's | ||||||||||||||||||||||
| # measures the fixture, not the parser. That is why these are not in `tak.toml`: tak gates | ||||||||||||||||||||||
| # everything it finds there, and a gate that fires when a fixture gets bigger teaches | ||||||||||||||||||||||
| # people to ignore it. | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # What is worth watching here is the *ratio* between the two columns, which is a property of | ||||||||||||||||||||||
| # the parsers and holds steady while the fixture changes. | ||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| out=${1:-/dev/stdout} | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Built somewhere else and moved into place at the end. The workflow calls this with | ||||||||||||||||||||||
| # `|| true`, because an informative table is not worth failing a run over — which means a | ||||||||||||||||||||||
| # failure part way through must not leave a truncated table behind for the comment to | ||||||||||||||||||||||
| # publish as though it were a comparison. | ||||||||||||||||||||||
| tmp=$(mktemp) | ||||||||||||||||||||||
| trap 'rm -f "$tmp" cachegrind.out.*' EXIT | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # The two binaries take a repeat count from the environment, so differencing two runs of the | ||||||||||||||||||||||
| # *same* binary isolates the parse: N=1 minus N=0 is one cold parse in a fresh process. | ||||||||||||||||||||||
| # Differencing two different binaries would fold in whatever they each do before `main`. | ||||||||||||||||||||||
| instructions() { | ||||||||||||||||||||||
| local binary=$1 n=$2 | ||||||||||||||||||||||
| PARSE_N="$n" valgrind --tool=cachegrind --cache-sim=no --branch-sim=no \ | ||||||||||||||||||||||
| "./target/release/$binary" use -g node@20 2>&1 | | ||||||||||||||||||||||
| sed -n 's/.*I *refs: *//p' | tr -d ',' | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| cold() { | ||||||||||||||||||||||
| local binary=$1 zero one | ||||||||||||||||||||||
| zero=$(instructions "$binary" 0) | ||||||||||||||||||||||
| one=$(instructions "$binary" 1) | ||||||||||||||||||||||
| echo $((one - zero)) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if ! command -v valgrind >/dev/null 2>&1; then | ||||||||||||||||||||||
| echo "valgrind is not installed, so there are no instruction counts to report" >&2 | ||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| usage_cold=$(cold parse-n) | ||||||||||||||||||||||
| clap_cold=$(cold parse-n-clap) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| { | ||||||||||||||||||||||
| printf '### Shadow comparison\n\n' | ||||||||||||||||||||||
| # The backticks in this block are markdown, not command substitution, and the single | ||||||||||||||||||||||
| # quotes are what keeps them literal. | ||||||||||||||||||||||
| # shellcheck disable=SC2016 | ||||||||||||||||||||||
| printf 'Parsing `mise use -g node@20` against a shadow of mise'"'"'s committed spec.\n' | ||||||||||||||||||||||
| printf 'Reported, not gated: the shadow grows as the derive learns to express more, so\n' | ||||||||||||||||||||||
| printf 'what to watch is the ratio rather than either column.\n\n' | ||||||||||||||||||||||
| printf '| | usage | clap | ratio |\n' | ||||||||||||||||||||||
| printf '|---|---:|---:|---:|\n' | ||||||||||||||||||||||
| printf '| instructions, cold parse | %s | %s | %sx |\n' \ | ||||||||||||||||||||||
| "$(printf "%'d" "$usage_cold")" "$(printf "%'d" "$clap_cold")" \ | ||||||||||||||||||||||
| "$((clap_cold / usage_cold))" | ||||||||||||||||||||||
|
Comment on lines
+58
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Use a floating-point ratio and validate the denominator.
Suggested calculation+ratio=$(
+ awk -v clap="$clap_cold" -v usage="$usage_cold" \
+ 'BEGIN { if (usage <= 0) exit 1; printf "%.2f", clap / usage }'
+)
printf '| instructions, cold parse | %s | %s | %sx |\n' \
"$(printf "%'d" "$usage_cold")" "$(printf "%'d" "$clap_cold")" \
- "$((clap_cold / usage_cold))"
+ "$ratio"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| printf '\n' | ||||||||||||||||||||||
| # Wall clock in the same process, which is the only way to see µs: a whole-process | ||||||||||||||||||||||
| # measurement cannot resolve a 2µs parse. | ||||||||||||||||||||||
| printf '```\n' | ||||||||||||||||||||||
| ./target/release/time-parse | ||||||||||||||||||||||
| printf '```\n' | ||||||||||||||||||||||
| } >"$tmp" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| cat "$tmp" >"$out" | ||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.