Repository navigation
Conversation
Adds a new assingment API to force scheduling of a fibre off the global queue. This is useful for validating hub migation in a determinisic fashion.
3 of 4 tasks
A wake performed on a general hub thread now pushes the woken fiber onto
the waker's own Chase-Lev deque (a lock-free owner push) instead of the
mutex-protected global run-queue. The waker's hub picks it up at its next
pick step, or an idle hub steals it. The global queue is left for the
cases with nowhere local to go: a foreign (non-hub) waker, an offload-hub
waker, a pinned fiber, controlled replay, or a full deque.
runloom_mn_woken_enqueue is the single routing point; all three former
global_runq_push sites (wake_g, the RUNNING_WOKEN release, the sweep
release) go through it. The wake state machine is unchanged: the caller
still takes the PARKED->QUEUED edge and the queue ref, and hub_main now
recognises a QUEUED g popped or stolen from a deque and runs the same
QUEUED->RUNNING claim + queue-ref drop it runs for a global pull. The
park-side surplus scan counts a deque of ONE as surplus under migration,
because the owner may be mid-fiber and never reach its pick step; the
producer kicks after every local push so the Dekker pair stays exact.
Default mode is byte-unchanged (nothing reaches QUEUED there).
Measured on the 3.14.4t-mig interpreter (both patches), 18-core arm64,
RUNLOOM_MIGRATION=1, cover builds, median of 3:
8 hubs, 8 concurrent ping-pong pairs base 341K -> new 665K agg rounds/s
(every wake off the global queue: 992K global pulls -> 0)
2 hubs, 1 ping-pong pair base 808K -> new 818K rounds/s
2 hubs, 64-way fan-out base 1.30M -> new 1.36M wakes/s
The single-pair case is within noise: with one waker at a time the global
mutex is uncontended, so the win is the lock under concurrent wakers.
Testing: tests/test_local_wake.py (4 tests; soaked 20x) plus test_mn,
test_chan, test_hub_pinning, test_offload_hubs, test_freethread_stress and
test_swarm_mn_sched (minus the deadlock tests) in migration mode, identical
pass/fail sets on this tree and the unmodified baseline; the default-mode
subset via run_isolated is all green on stock 3.14.4t.
Two pre-existing migration-mode gaps surfaced and are recorded in
docs/dev/MIGRATION_DEFAULT_ANALYSIS.md, not fixed here: the deadlock census
is inert (per-g-tstate disables preemption, which disables the sysmon
instrumentation the census is gated on), and the fiber_n bulk-spawn +
WaitGroup swarm tests time out. Pinned cross-hub wakes also run at ~3.4K
rounds/s in both trees, which points at the deep-park kick path.
sched: Go-style local wake under migration mode
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.
Adds a small placement API so a test can assert which hub a fibre runs on instead of measuring it statistically.
mn_fiber(fn, hub=N)spawns on hub N and keeps it on that hub's local queue rather than the stealable deque.G.pin(N)confines a fibre's later resumes to hub N, enforced on the consumer side of the global run-queue.pin(None)clears it.mn_current_hub()returns the hub running the caller.G.stack()reports state from the wake state machine under migration mode, where there is no snapshot.Offload spawns are pinned through the same path, so a woken offload fibre cannot be pulled onto a general hub under migration; the world-yield scan now skips offload hubs for the same reason.
Tests:
tests/test_hub_pinning.py(needs both CPython migration patches; skips otherwise) and two additions totests/test_offload_hubs.py.🤖 Generated with Claude Code