Repository navigation
Reduce runner metadata lookup overhead while preserving Bash 3.0 support #1392
Description
Large test files repeatedly scan provider and annotation arrays while dispatching tests. Reduce this runner overhead while keeping Bash 3.0+ support and identical test behavior. Use modern Bash facilities automatically only where measurements justify a separate implementation.
Acceptance scenario
A file containing many short tests, mixed data providers, and timeout/retry/skip annotations runs the same selected cases and data sets, with the same outcomes and ordering rules, before and after the change. Metadata resolution costs less, with a measurable end-to-end improvement on the affected workload. The scenario works sequentially and in parallel on Bash 3.0 and newer.
Evidence and scope
Inspected revision: 7e3de3d65d63f26a7702e53f20e5deeee373c85c. Recheck current main before implementation.
src/helper/provider.sh:277:provider_for_functionscans the provider map for each lookup.src/helper/annotations.sh:52:annotations_for_functionscans the annotation map for each lookup.src/runner/exec.sh:179,344,546: dispatch and execution consume these lookups, including annotation resolution in both the runner and test body.src/helper/discovery.sh:353: header counting also consumes provider metadata.
These observations identify repeated work, not a measured speedup. Existing optimizations already include native Bash 5 timing, Bash 4.3+ wait -n, and per-file metadata scanning.
Limit implementation to metadata resolution and its consumers. Result transport, scheduler changes, timeout watchdog redesign, coverage optimization, and removal of test isolation belong in separate issues.
Steps
- Establish the baseline. Inspect current callers, map resets, header-cache reuse, filtering, and execution boundaries. Reuse existing benchmark fixtures where possible. If new benchmark infrastructure is needed, land it before the optimization and measure current main. Record commit, OS, actual Bash version, commands, and sample method.
- Measure representative workloads. Compare small files and large files (for example 10, 100, and 1,000 short tests), with no metadata, dense annotations, and mixed providers. Include multiple data sets, multiple files, sequential mode, and bounded parallel mode. Measure total wall time as well as lookup cost and process counts. Do not use traced execution for wall-time claims.
- Choose the smallest measured improvement. First evaluate resolving metadata once and carrying its index or values through dispatch, including reuse across data sets where semantics permit. Moving the same linear scan to another function alone is insufficient. Evaluate an associative-array index on modern Bash only if it provides a repeatable additional benefit. Keep a working Bash 3.0 path and avoid adding dependencies or configuration flags.
- Prove behavior before changing runtime code. Add focused failing regressions for the chosen contract or work reduction. Cover missing entries, map reset between files, changed-file cache invalidation, filtered/randomized order, providers, and annotation defaults/overrides. Preserve invalid-annotation and unusable-provider failures. Use existing tests where they already prove these cases.
- Implement and compare. Keep public helper behavior and return slots intact. Preserve setup/teardown, retries, timeout behavior, test isolation, and parallel result aggregation. Select any modern capability outside hot loops. Shared code must parse on Bash 3.0; do not assume a version guard protects unsupported syntax. Preserve compatibility with the single-file build.
- Verify compatibility and performance. Run the affected behavior tests on actual Bash 3.0, 3.2, representative 4.x releases, and 5.x, including the boundary version for every new capability. A compatibility setting on modern Bash is not a substitute. Alternate baseline and candidate runs in the same filesystem location, repeat anomalous measurements, and report medians and variation. Extend the applicable fork regression if process costs change.
- Complete delivery. Run the full local gate once after the final change set:
./bashunit tests/,./bashunit --parallel tests/,make sa, andmake lint. Validate the built artifact, add the user-visible performance change to CHANGELOG, and document any architectural decision in an ADR. Include the measurement table and compatibility results in the PR.
Acceptance criteria
- Bash 3.0 remains supported by default, without extra dependencies or user flags.
- Any modern implementation is selected automatically and passes the same behavioral cases as the fallback.
- Metadata does not leak between files or become stale after cache invalidation.
- Test selection, data sets, annotation behavior, outcomes, exit status, and ordering rules are unchanged in sequential and parallel runs.
- Measurements demonstrate an end-to-end improvement beyond observed noise on the target workload, with no repeatable regression on small files or the Bash 3 fallback.
- Report lookup scaling, wall-time samples, process-count effects, and tested versions. Do not claim a percentage improvement before measuring.
- Relevant regression tests, the full local gate, and built-artifact validation pass.
If metadata resolution is not a material cost or the candidate cannot improve end-to-end time reliably, publish the measurements and stop this optimization. Use the evidence to choose the next runner bottleneck instead of adding an unproven second implementation.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
Chemaclass commentedon Oct 24, 2026
Completed in #1395, merged as 07fb33d. Verified that the metadata implementation on current main is byte-identical to the validated source files.
Maps above 64 entries use a portable index. Smaller maps keep direct scans. This preserves Bash 3.0 support without dependencies, configuration flags, or a separate modern implementation. Regression tests cover bounded lookup work, missing entries, literal names, first-match behavior, resets, cache invalidation, providers, annotation overrides, filtering, random order, and sequential/parallel execution. ADR-014 records the decision.
The measurement table and method are in #1395. Median wall time for 1,000 densely annotated functions fell from 11.503s to 5.038s on macOS Bash 3.2, from 10.024s to 5.185s on Linux Bash 3.0, and from 5.951s to 2.475s on Linux Bash 5.3. The macOS mixed-provider workload fell from 21.067s to 9.444s. Warmed small-file comparisons showed no consistent slowdown. Indexing adds no external commands or command substitutions, and existing process budgets passed.
Validation recorded for the delivered change:
All acceptance criteria are complete.