Problem
precompute_file_stats calls compute_file_coverage once per tracked file,
and each call reads the whole file into a Bash array and classifies it line by
line. It is the last Bash per-line loop in the report phase, and the second
biggest cost left after #1085.
Measured on Bash 3.2 arm64, 128 tracked src/*.sh files, 3551 hit records:
| 128 files |
|---|
| per-file Bash loop (today) | 1956 ms |
| one awk fork for all of them | 97 ms |
Proposal
One awk invocation for the whole phase, not one per file. awk takes a manifest
of <hits block>\t<source> pairs and walks both with getline, so the cost
of a fork is paid once for the run instead of 128 times, and the per-line work
happens where it is cheap.
The hit data is already grouped into per-file blocks by #1057, so the manifest
is the only new plumbing. compute_file_coverage keeps its contract for the
single-file callers (get_file_stats).
Verification
Output is identical for all 128 files, executable and hit counts alike, over
synthetic hits that exercise continuation propagation and repeated lines.
Problem
precompute_file_statscallscompute_file_coverageonce per tracked file,and each call reads the whole file into a Bash array and classifies it line by
line. It is the last Bash per-line loop in the report phase, and the second
biggest cost left after #1085.
Measured on Bash 3.2 arm64, 128 tracked
src/*.shfiles, 3551 hit records:Proposal
One awk invocation for the whole phase, not one per file. awk takes a manifest
of
<hits block>\t<source>pairs and walks both withgetline, so the costof a fork is paid once for the run instead of 128 times, and the per-line work
happens where it is cheap.
The hit data is already grouped into per-file blocks by #1057, so the manifest
is the only new plumbing.
compute_file_coveragekeeps its contract for thesingle-file callers (
get_file_stats).Verification
Output is identical for all 128 files, executable and hit counts alike, over
synthetic hits that exercise continuation propagation and repeated lines.