Repository navigation
Wake the dispatch and runspace loops as soon as a job finishes - #31
Merged
Merged
Conversation
The dispatch loop slept 50 ms on every pass, even one where a job had just finished, and noticed the free slot only after another sleep. That capped each slot at about 8 programs a second. The runspace loop's 100 ms sleep capped short workers at about 9 jobs a second per slot. The dispatch loop now goes straight round after a pass where a job finished, and otherwise waits on the exit handles of programs still running plus the cancel token, capped at 50 ms. It waits only on programs that haven't exited, so a -JobPollCompleted that keeps saying "not done" can't spin a core. It falls back to a sleep for a job with no real process or more than 63 running. The runspace loop does the same with its workers' wait handles and a 100 ms cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refilling a freed slot at once let a dispatcher on a shared SemaphoreSlim keep every slot until its queue ran out, so a sibling got none. A dispatcher on a shared budget still pauses after a finished job. WaitAny holds at most 63 handles on an STA thread, so waiting on 63 plus the token threw under PowerShell 7. Both loops now wait on up to 62 plus the token, and on those even when more are running, rather than falling back to a sleep. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong: the dispatch loop slept 50 ms on every pass, even after a job had just finished, and only refilled the slot after the next sleep. That capped each slot at about 8 programs a second. The runspace loop's 100 ms sleep capped short workers at about 9 jobs a second per slot.
What changed:
-JobPollCompletedthat keeps saying "not done" can't spin a core.WaitAnyholds 63 handles at most on an STA thread.SemaphoreSlimstill pause after a finished job. Without that, one with a queue kept every slot until it ran out and its sibling got none.Behavior users can notice:
-PollCallback,-AbortPollCallback,-GroupReleaseCheck) can run many times more often when jobs finish quickly. The README now says to keep them cheap.-JobFinalizecan start within milliseconds of the failure. The README says to cap retries and not count on the gap.Measured (PowerShell 5.1 and 7, new harness section AB):
cmd /c exit 0,-MaxConcurrent 1(5.1)-MaxParallel 1(5.1)Two dispatchers sharing one slot alternate as before (
ABABAB).Tested: the harness passes on 5.1 and 7 (300 assertions, none skipped). The two timing tests fail on
main. The turn-taking test fails against the same change without the pause. New checks also cover a lagging-JobPollCompleted, 70 programs and 70 workers at once, a job whose.Procisn't a process, and a batch inside a worker.🤖 Generated with Claude Code