Skip to content

bench: measure both sides of every row on stdout+stderr - #3774

Merged
KuSh merged 1 commit into
rtk-ai:developfrom
KuSh:bench/symmetric-stderr-measurement
Sep 30, 2026
Merged

KuSh merged 1 commit into
rtk-ai:developfrom
KuSh:bench/symmetric-stderr-measurement

Conversation

@KuSh

@KuSh KuSh commented Aug 30, 2026 •

Copy link
Copy Markdown
Collaborator

The raw side of each benchmark row is measured with 2>&1 and the rtk side with 2>/dev/null, so the two columns are not the same measurement.

rtk forwards the stderr it does not filter. Dropping that stream from the rtk column books a passed-through stream as if the filter had removed it, and it hides the failure mode the rows exist to catch: a filter that goes silent while the tool reports on stderr scores as a saving. The golangci-lint row reads 157 -> - and fails the run for producing nothing, with no way to see that the diagnostic went to the other stream all along.

Why this cannot make rtk look worse

For an identical measurement rtk is better or equal by construction. stderr is common to both sides, so never-worse reduces to filtered <= stdout.

rg in CI

Measuring stderr also shows when the tool under test is missing. The CI runner has no rg, so the rg rows compared the shell's rg: command not found with rtk's own error and went negative. The benchmark job now installs ripgrep next to tree, and the rg section gets the same command -v guard as tree, so it is skipped when rg is absent.

The run reports 0 negative and 0 fail both ways:

rg rg rows
installed (CI) rg fn 125431 → 4028, rg struct 3434 → 2599, rg -l 800 → 675, rg -c 895 → 895
absent (local, rg hidden from PATH) section skipped

The good/warn split moves by a row or two between machines and with what is installed locally, so it is not a property of this change and I have deliberately not quoted it as one.

Verified in golang:1.27 that the go rows read 220 -> 35 GOOD on golangci-lint v2.13.2, and 157 -> 157 — a tie, not a red run — if the v2 install were ever reverted.

Independent of the other benchmark work

This does not depend on #3773 and does not change its numbers (220 -> 35 either way). It is a measurement-methodology change that touches every row, which is why it is separated out rather than folded in.

It does read best after #3772: until stdout-only filters forward stderr at all, the golangci-lint row stays FAIL regardless of how it is measured.

@aeppling

Copy link
Copy Markdown
Contributor

Hey @KuSh , thanks for this correctness fix in benchmark, LGTM

Could you also install rg in the ci runner so benchmark pass ? all results look same length so I suspect a problem with rg execution in this environment.

"tree" command has a guard for this, we could add an install step and the guard as well

@aeppling aeppling self-assigned this Sep 30, 2026
The raw side was measured with 2>&1 and the rtk side with 2>/dev/null, so the two
columns were not the same measurement. rtk forwards the stderr it does not
filter, and dropping that stream books it as if it had been removed.

It also hid the failure mode this fixture is meant to catch. A filter that goes
silent while the tool reports on stderr scored as a saving; the golangci-lint row
read 157 -> - and failed the run for producing nothing, with no way to see that
the diagnostic had gone to the other stream all along.

For an identical measurement rtk is better or equal by construction: stderr is
common to both sides, so never-worse reduces to `filtered <= stdout`.

Measuring stderr also shows when the tool under test is missing. The CI runner
has no rg, so the rg rows compared the shell's "command not found" with rtk's
own error and went negative. The benchmark job now installs ripgrep, and the rg
section is skipped when rg is absent, as the tree section already is.

The run reports 0 negative and 0 fail both with rg installed (rg fn 125360 ->
4083) and without it (section skipped). The good/warn split moves by a row or
two between machines and with what is installed, so it is not a property of this
change.

Verified in golang:1.27 that the go rows read 220 -> 35 GOOD on v2.13.2, and
157 -> 157 -- a tie, not a red run -- if the v2 install were ever reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KuSh
KuSh force-pushed the bench/symmetric-stderr-measurement branch from 0950ceb to 0f6b844 Compare September 30, 2026 21:26
@KuSh

KuSh commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks! Done in 0f6b844: the benchmark job now installs ripgrep next to tree, and the rg section gets the same command -v guard as tree, so it is skipped with "⏭️ rg (not installed, skipped)" when rg is not there.

You were right about the cause. With stderr now measured on both sides, the rg rows were comparing the shell's rg: command not found (14 tokens) with rtk's own error (22 tokens), hence the identical lengths. The benchmark job is green on this head: with rg installed the four rows read 125431 → 4028, 3434 → 2599, 800 → 675 and 895 → 895, and the run reports 0 negative, 0 fail. Locally with rg hidden from PATH the section is skipped and the run is clean as well.

I also rebased onto the current develop.

@KuSh
KuSh merged commit 947de11 into rtk-ai:develop Sep 30, 2026
12 checks passed
@KuSh
KuSh deleted the bench/symmetric-stderr-measurement branch September 30, 2026 22:06
@rtk-release-bot rtk-release-bot Bot mentioned this pull request Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants