Measured
| assertion |
count |
wall |
per call |
assert_same |
2000 |
~130 ms |
0.065 ms |
assert_contains |
2000 |
~180 ms |
0.09 ms |
assert_matches |
500 |
~1.25 s |
2.5 ms (~38x) |
Stable across three runs each.
Why, and why it is not a bug
assert_matches forks grep -E per call. .claude/rules/perf-fork-budget.md
already records the reason — Bash 3.2 changed whether a quoted right-hand side
of [[ =~ ]] is a regex or a literal, so at the Bash 3.0 floor the same pattern
would match differently across supported versions, and removing the fork means
picking one semantic and breaking the other.
Not proposing to change it. That trade is decided, and the rule says not to
chase it.
What is missing
The cost was never quantified anywhere, and users have no way to know. A suite
asserting inside a large loop pays 38x without a hint that a cheaper assertion
would do.
- Quantify it in the internal rule, so the trade is weighable rather than just
asserted.
- Note it in
docs/assertions.md, pointing at assert_contains when the
pattern is a fixed substring.
Measured
assert_sameassert_containsassert_matchesStable across three runs each.
Why, and why it is not a bug
assert_matchesforksgrep -Eper call..claude/rules/perf-fork-budget.mdalready records the reason — Bash 3.2 changed whether a quoted right-hand side
of
[[ =~ ]]is a regex or a literal, so at the Bash 3.0 floor the same patternwould match differently across supported versions, and removing the fork means
picking one semantic and breaking the other.
Not proposing to change it. That trade is decided, and the rule says not to
chase it.
What is missing
The cost was never quantified anywhere, and users have no way to know. A suite
asserting inside a large loop pays 38x without a hint that a cheaper assertion
would do.
asserted.
docs/assertions.md, pointing atassert_containswhen thepattern is a fixed substring.