Probe consteval coverage in batched rounds across all headers - #386
Conversation
Key each trap on (header index, __LINE__) so every library header is instrumented in one work directory, arm every uncovered probe point at once and let GCC report each independent evaluation that throws, repeating with the found points disarmed until a round finds nothing. Batches are interleaved so neighbouring points do not mask each other, and translation units are probed cheapest first. The CI job returns to a single runner. Closes #374.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #386 +/- ##
==========================================
+ Coverage 72.79% 74.57% +1.78%
==========================================
Files 12 15 +3
Lines 838 1003 +165
Branches 221 221
==========================================
+ Hits 610 748 +138
- Misses 22 49 +27
Partials 206 206
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Library headers use the .hh suffix; the coverage script no longer needs a special case for it.
|
|
|
I'm struggling to decipher why arming multiple traps at once is valid. The speedup is impressive and makes sense but it's unclear to me (from reading code and comments) why we can arm multiple traps at the same time. |
ProbePoint carries its trap key instead of looking the header up in INSTRUMENTED_HEADERS on every call, and probe_translation_unit's docstring says why arming many traps in one compile is sound.
|
Two properties make it sound. No false positives. A trap only throws when the evaluator executes it, and the diagnostic names the trap that threw. So every No permanent false negatives. A throw aborts only its own top-level constant evaluation; GCC carries on with the rest of the translation unit and reports each failed evaluation separately. Within one evaluation, only the first armed trap on its path reports, and any armed trap after it is masked. The next round disarms everything found so far, so the evaluation now runs past that point and reports the next armed trap on its path. Any trap the test suite evaluates is preceded on its path only by traps the suite also evaluates, so by induction it is reported once those are disarmed. The armed set shrinks every productive round, so this terminates, and a round with no new hits means no remaining armed trap is on any evaluation path. Cascading errors from an aborted evaluation (incomplete class, missing member) are not trap diagnostics, so they are ignored, and the evaluations they suppressed run in a later round once the trap is gone. A compile that fails with no trap firing raises instead. Small illustration, three consteval functions with traps The one-compile-per-probe script and this one give the same 150/177, identical per header, which is the empirical check. cef9446 moves this explanation into the |
|
|
jbcoe
left a comment
There was a problem hiding this comment.
Thanks for this - a significant improvement.
Closes #374.
Replaces one compile per probe point with batched rounds, and instruments every library header instead of just
protocol.hh.Timings
The CI probe step for the same 177 probe points, single runner unless stated:
protocol.hhonly)The whole job now takes 5 minutes, and
timeout-minutesdrops from 90 to 30.Locally, against the one-compile-per-probe script from #369 with
name_mangling_tests.ccadded:Both scripts report 150/177 probe points covered, with identical per-header LCOV records.
How
(header index, __LINE__), so all headers are instrumented in one work directory and one-includefile arms any subset of them.name_mangling_tests.ccis now included), soprotocol_test.cconly ever arms what the cheaper ones left uncovered.if constexprno-ops, so they cost the constant evaluator nothing.