kj-rs-tokio: a kj::EventPort driven by a per-thread tokio runtime - #7011
kj-rs-tokio: a kj::EventPort driven by a per-thread tokio runtime#7011danlapid wants to merge 1 commit into
Conversation
|
APIError: Invalid Anthropic API Key |
2 similar comments
|
APIError: Invalid Anthropic API Key |
|
APIError: Invalid Anthropic API Key |
|
@danlapid Bonk workflow failed. Check the logs for details. View workflow run · To retry, trigger Bonk again. |
0c3b740 to
c7ad8cf
Compare
c7ad8cf to
db5ac05
Compare
Merging this PR will degrade performance by 8.18%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
Second piece of the Rust I/O backend split (on top of the kj-rs bridge rework): TokioEventPort implements kj::EventPort over a per-thread tokio current_thread runtime, so a KJ event loop sleeps by parking inside tokio's scheduler -- tokio tasks (and, in the next piece, tokio I/O) run whenever KJ would otherwise block. - wait()/poll() park in LocalSet::block_on on the runtime, woken by cross-thread wake(), same-thread notify_runnable() (a task re-entered C++ and armed a KJ event), or the next KJ timer deadline. - Sub-millisecond KJ timers bypass tokio's ~1 ms timer wheel via a lazily-spawned high-resolution timer thread (mach_wait_until on macOS, clock_nanosleep(TIMER_ABSTIME) on Linux; Windows stays on the wheel). - kj_rs_tokio::spawn() enqueues !Send futures onto the loop's LocalSet, pinned to the loop thread per the bridge's single-thread waker axiom. - setupTokioAsyncIo() yields an event loop + wait scope only; the I/O providers over this port arrive in the kj-rs-io piece. This adds tokio's `sync` feature (Notify) to the workspace; no new crates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
db5ac05 to
ff4d77b
Compare
Groundwork for the tokio-backed Rust I/O backend (kj-rs-tokio / kj-rs-io,
landing separately); kj-rs itself stays a pure Promise<->Future bridge.
cell (non-atomic kj::Refcounted; the bridge's single-thread axiom) that
arms the owning FuturePollEvent directly via Event::armDepthFirst(). The
cell's link to the event is weak and structurally invalidated when the
event dies, so wakers Rust retains past the future's lifetime (e.g.
parked in a channel's AtomicWaker) neutralize into safe no-ops instead of
arming a freed event. Waker ownership round-trips through RawWaker data
slots via kj::Rc::disown()/reown() -- hence the capnp-cpp pin bump to the
current v2 head, which carries those (merged upstream).
intrusive weak link (RustPromiseAwaiter::link / FuturePollEvent::leaves).
to its first suspension point at conversion, so KJ callers no longer need
a manual .eagerlyEvaluate(nullptr); RustFuture::lazily() is the escape
hatch for the rare cold case.
rejected promise) instead of aborting the process, mirroring the sync
bridge's catch_unwind path.
drives tokio tasks inside its own wait() (the upcoming kj-rs-tokio) can
nudge itself out of a blocking park; null/no-op by default.
unsafe into named FFI islands: deny(unsafe_code) crate-wide, re-allowed
per-module only where the FFI seam genuinely needs it.
umbrella, keeping kj-rs (and everything built on it) off the concrete kj
OS event loop.
FuturePollEvent shared-event semantics (shared-event-test), and expanded
future/awaiter coverage.