Problem
The trap engine collects hits into a 100-entry in-memory buffer
(_BASHUNIT_COVERAGE_BUFFER, _BASHUNIT_COVERAGE_BUFFER_LIMIT=100) and
flushes when it fills. A buffer that lives in a variable dies with the subshell
that filled it, so anything recorded inside a short-lived command substitution
never reaches the data file.
Running tests/unit/assert/basic_test.sh against --coverage-paths src:
| Bash 5 | hits | wall |
|---|
| trap, buffer=100 (today) | 196/11438 | 4612 ms |
| trap, write-through | 236/11438 | 4258 ms |
| xtrace | 238/11438 | 2147 ms |
The 40 missing lines are real code: bashunit::temp_dir and friends, executed
inside $( ). Deterministic across runs.
On Bash 3.2 there is no loss (234 either way) — so the same project reports
different coverage depending on the Bash version, which is worse than being
uniformly wrong.
The buffer also costs more than it saves
| buffer=100 | write-through |
|---|
| Bash 3.2 (macOS, trap is the only engine) | 8896 ms | 7080 ms |
| Bash 5 | 4612 ms | 4258 ms |
Appending to a growing shell string is not cheaper than an >> append per
line, so the buffer is pure downside on both counts.
Proposal
Write through, and delete the buffer and its flush bookkeeping. Points to
verify before landing:
--parallel: workers already write to their own data files, so concurrent
appends stay per-worker; confirm no shared-target case remains- the fork budget:
>> per line is a syscall, not a fork, so
bashunit_coverage_forks_test.sh should be unchanged
Related
xtrace is 2x faster than trap on Bash 5 and auto already selects it
there, so this is mainly about the Bash 3.x/macOS path — where trap is the only
option.
Problem
The trap engine collects hits into a 100-entry in-memory buffer
(
_BASHUNIT_COVERAGE_BUFFER,_BASHUNIT_COVERAGE_BUFFER_LIMIT=100) andflushes when it fills. A buffer that lives in a variable dies with the subshell
that filled it, so anything recorded inside a short-lived command substitution
never reaches the data file.
Running
tests/unit/assert/basic_test.shagainst--coverage-paths src:The 40 missing lines are real code:
bashunit::temp_dirand friends, executedinside
$( ). Deterministic across runs.On Bash 3.2 there is no loss (234 either way) — so the same project reports
different coverage depending on the Bash version, which is worse than being
uniformly wrong.
The buffer also costs more than it saves
Appending to a growing shell string is not cheaper than an
>>append perline, so the buffer is pure downside on both counts.
Proposal
Write through, and delete the buffer and its flush bookkeeping. Points to
verify before landing:
--parallel: workers already write to their own data files, so concurrentappends stay per-worker; confirm no shared-target case remains
>>per line is a syscall, not a fork, sobashunit_coverage_forks_test.shshould be unchangedRelated
xtraceis 2x faster thantrapon Bash 5 andautoalready selects itthere, so this is mainly about the Bash 3.x/macOS path — where trap is the only
option.