Skip to content

Analyze the code once per run, not once per child process - #2984

Merged
nohwnd merged 1 commit into
mainfrom
cc-child-points-once
Aug 22, 2026
Merged

Analyze the code once per run, not once per child process#2984
nohwnd merged 1 commit into
mainfrom
cc-child-points-once

Conversation

@nohwnd

@nohwnd nohwnd commented Aug 22, 2026

Copy link
Copy Markdown
Member

Every test that goes through Invoke-InNewProcess collects coverage in the child, and it got there by calling Enter-CoverageAnalysis for the whole target. That walks the Ast of every analyzed file to build the ~10k tracer points, and the points come out the same every time, so a run with 31 such tests did that work 32 times.

test.ps1 already has the list for its own tracer, so it writes it out once now and the children build their tracer from the file. A child only reports back path and line:column, so the coordinates are all it needs and the command text stays out of the file.

Coverage output is the same, still 31 child runs, 71 merged points, 87.8%.

Time

test.ps1 -CI -CC locally went from 188s to 87s.

On CI, this PR (build 3940) against #2982 (build 3939), same pipeline on the same base:

leg before after
PS7 Ubuntu 22.04 7:43 3:41
PS7 Ubuntu 24.04 7:03 3:27
PS7 macOS 14 10:39 3:59
PS7 macOS 15 9:03 4:23
PS7 Windows 2022 7:13 4:40
PS7 Windows 2025 9:13 5:01
PS 5.1 Windows 2022 13:24 9:38
PS 5.1 Windows 2025 15:08 12:07
build stage 0:53 0:58
wall time, what a PR waits for 16:10 13:13
machine time, all legs added up 79:26 46:56

The legs run in parallel, so a PR takes the build stage plus the slowest leg, 16:10 down to 13:13. Build 3940 finished in 14:00, the rest is the stage transitions. I am not comparing against 3939's own total of 24:18, it was queued next to another build and that number says more about the queue than about this change.

The 32 minutes of machine time is what comes back when several PRs run at once, which is when the queue is what we actually wait for.

PS 5.1 gains the least and sets the pace now, 12:07 of the 13:13. That is a separate problem from this one.

Split the translation out of Start-TraceScript into Get-TracerPoint so both sides use it, added tests for it and for the text form the children read, and made the run fail when no child coverage arrives. A child cannot report a failure, it falls back to a plain run, so a break in this plumbing would otherwise only show as coverage quietly going down.

🤖

Tests that go through Invoke-InNewProcess collect coverage in the child, and
each child called Enter-CoverageAnalysis for the whole target to get there. That
walks the Ast of every analyzed file to produce about 10k tracer points, and it
produces the same points every time, so with 31 such tests we did the same work
32 times per run.

test.ps1 already has that list for its own tracer. Write it out once, and let the
children build their tracer from the file instead of deriving it again. They only
report back path and 'line:column', so the coordinates are all they need and the
command text stays out of the file.

Local run of test.ps1 -CI -CC: 188s to 87s. Coverage is unchanged, still 31 child
runs, 71 merged points, 87.8%.

Split the translation out of Start-TraceScript as Get-TracerPoint so both sides
can use it, and fail the run when no child coverage arrives. A child cannot
report a failure, it falls back to a plain run, so a break in this plumbing would
otherwise only show up as coverage silently going down.

🤖
@nohwnd
nohwnd merged commit 62eab81 into main Aug 22, 2026
13 checks passed
@nohwnd
nohwnd deleted the cc-child-points-once branch August 22, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant