In short: each subcommand loads the repo through the workspace helper, resolves its inputs once, runs the operation once and reports how long that took, then hands the same closure to Criterion, which samples it repeatedly and compares against a saved baseline. Default builds don't contain it: the feature is off by default.
The group is BenchCommand, help text "Commands for benchmarking
internal operations", marked #[command(hide = true)]. It is the Bench variant of the
top-level Command enum, compiled only under #[cfg(feature = "bench")]
(source, dispatch), and
cmd_bench matches on it. The feature only pulls in
criterion and is not in default (source).
1. Command-line surface
| Subcommand | Help text | Arguments | What is timed |
|---|---|---|---|
common-ancestors | "Find the common ancestor(s) of a set of commits" | REVISION1, REVISION2 | index.common_ancestors of the two commits (source) |
is-ancestor | "Checks if the first commit is an ancestor of the second commit" | ANCESTOR, DESCENDANT | index.is_ancestor (source) |
resolve-prefix | "Resolve a commit ID prefix" | PREFIX (hex) | index.resolve_commit_id_prefix (source) |
revset | "Walk the revisions in the revset" | REVISIONS… or -f FILE, one required | resolving, evaluating and streaming each revset (source) |
All four flatten the shared Criterion options (CriterionArgs):
| Flag | Default | Meaning |
|---|---|---|
-s, --save-baseline NAME | base | "Name of baseline to save results" |
-b, --baseline NAME | none | "Name of baseline to compare with". Same group as --save-baseline, so they conflict; a missing baseline is not an error (source). |
--sample-size N | 100 | "Sample size for the benchmarks, which must be at least 10"; clap rejects smaller values. |
The global flags are on the CLI page.
3. End-to-end flow
4. Core architecture touchpoints
| Piece | Role here |
|---|---|
| Index | What three of the four benchmarks measure directly: common ancestors, ancestry, and prefix resolution, each called on workspace_command.repo().index(). |
| Revsets | bench revset parses each expression once, then times resolution with a symbol resolver that has no extensions ("without parsing/evaluating short-prefixes"), evaluation, and counting the stream (source). With -f, blank lines and lines starting with # are skipped (source). |
| Store caches | Before each bench revset batch the workspace is reloaded, because "repo.reload_at() isn't enough to clear store cache", and the index is preloaded with readonly_index (source). |
| Working copy, operation log | Only the normal workspace helper's snapshot on load; nothing is written by the benchmarks themselves. |