Repository navigation
perf(ffi): resume a Python wake on the loop's own thread without the socket pair - #564
Merged
Merged
Conversation
Quest-Claim: a0747c7e18be8f1a
…socket pair Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
marked this pull request as ready for review
November 4, 2026 04:52
|
This run was cancelled before it finished. |
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.

Problem
A future the exporter's Python awaits resumed through the queue's socket pair even when Rust woke it on the event loop's own thread, as a task's
write_framewakes a parkedread_frame: a write, a select wakeup, and reads, about 5 µs of a 21 µs woken read (#407).Approach
asyncio._get_running_loop()into a thread-local. A thread where none runs stops looking until a loop polls or takes there again, so calls outside a loop cost what they did._resume, which schedules the loop's dispatch withcall_soon. Dispatch still runs at a step boundary, as the socket's reader did, so a token can never reach the loop before its parked future exists. If that loop isn't the one running (which shouldn't happen), or_resumeraises, the queue's socket signals it instead. AKeyboardInterruptraised in_resumeis re-armed withPyErr_SetInterrupt.Queue.take(read)skips the socket read on the direct path.Tests in
tests/api.pycover these cases, and the existing wake-latch and cancel tests still pass:Wakercall it once;just ciandjust ffi moqpass.Measurements
moq/bench/export.py(the Python leg ofjust ffi bench) on main and on this branch, interleaved with BoltFFI 0.31.1's Python harness from moq@0f986d9 in the same run, rotating order. The host is shared, with load average 5 to 12 on 32 threads, CPython 3.14.8. Medians of 9 rounds, min to max in parentheses:yield_once28,711 ns (26,603 to 40,181)sequence152 ns (145 to 231)A second run of 12 rounds put the woken read at 20,681 (19,321 to 28,668) on main against 17,558 (15,012 to 25,073) here.
The cost is that each call inside a running loop pays for the lookup. Over 6 rounds, a handle call in a running loop went from 104 to 118 ns (medians). A frame written and read without suspending went from about 1,000 to about 1,150 ns, since it makes 3 or 4 calls. Each woken read saves about 5 µs.
BoltFFI's
yield_oncemeasured 28.7 µs on this host, against the 10 µs bench/ffi/README.md records, so this host runs about 2.9 times slower than that one. Scaled the same way, this PR's woken read (15.7 µs) would be about 5.5 µs there.Impact
_n.Queuenow takes its loop, and the runtime reserves_resume.Alternatives
__await__stores its parked future, and the wake would be lost.Follow-ups
None.
Review
quest review, Codex gpt-6.1-sol at medium effort, round 1 at head 2ac3985 and round 2 at head 2022479. No findings.Checks run locally on 2022479:
just ci(ffi lint and the 21 fixture tests driving C, C++, Kotlin, Python, Swift, Go, and Dart), andjust ffi moqon every language. Not run:just ffi android, which needs a device.🤖 Generated with Claude Code