pub struct DifferentialSession { /* private fields */ }Expand description
Three revision worktrees whose lifetime is a whole calibration run rather than a single observation.
The observation cost the harness cannot avoid is compiling the project
under test three times. The cost it can avoid is compiling the project’s
dependencies three times per observation, which is what a fresh worktree
per observation forces: the operator’s --target-dir is tree-relative (the
ledger refuses any target directory that escapes its worktree), so
destroying the tree destroys the build directory with it and the next
observation starts from zero. Holding the same three trees open across
observations and moving them with git checkout keeps those build
directories alive. Measured on rust-lang/log, one run: 16.1 s in a
fresh tree against 12.0-13.4 s in a held tree switched to a new
revision.
Three properties are deliberately preserved, because each of them is load bearing for what the calibration claims:
- Every run is still really run. A held tree makes a run cheaper, never
skipped:
cargo testre-links and re-executes the test binaries even when nothing changed (measured: four test binaries execute in a fully warm tree). That is what the ledger’sindependent_runsassumption needs, and it is why this is not a result cache. - The three trees stay separate. Each keeps its own build directory, so the cross-tree artifact contamination that invalidated an earlier receipt cannot recur, and the three concurrent runs still cannot contend on one tool lock.
- Nothing survives the run. The worktrees and their root are removed by
Self::close, and again byDropif a caller returns early, so an operator’s repository is left as it was found.
What it does change, stated rather than buried: an observation now starts in
a tree that holds an earlier observation’s untracked build output.
Tracked content is exact — the checkout is forced, so the tree matches the
revision — but a command that writes untracked files into its tree will see
them again. Callers that need a pristine tree per observation still have
one: run_differential opens and closes a session around a single
observation, and choir-bridge calibrate --fresh-worktrees selects that
path for a whole run.
Which tree plays which role is decided per observation: a revision is
assigned to a tree that is already sitting on it, when one is. Replaying
consecutive first-parent merges — the shape of a calibration corpus — makes
this pay every observation, because a merge’s first parent is the
previous observation’s merge: the tree that just ran that merge becomes the
parent-a tree with a no-op checkout, so its command rebuilds nothing at
all. Measured on rust-lang/log, one warm tree, solo: 8.9 s for a
no-op revision against 15.0 s for a one-merge move.
Implementations§
Source§impl DifferentialSession
impl DifferentialSession
Sourcepub fn open(repo: &Path) -> Self
pub fn open(repo: &Path) -> Self
Names a session root under repo. Creates nothing until the first
observation; opening cannot fail.
Sourcepub fn close(self) -> Result<(), String>
pub fn close(self) -> Result<(), String>
Removes the three worktrees and the session root, reporting the first
failure. Drop repeats this as a best-effort backstop, so a caller that
returns early still leaves nothing behind — but only close can tell
the caller that cleanup failed.
§Errors
A worktree or the session root could not be removed.