diff options
author | Matt Mastracci <matthew@mastracci.com> | 2023-05-30 18:02:52 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-30 18:02:52 -0600 |
commit | 489d2e81c3e53ed689f51dc9d76c007d487aa101 (patch) | |
tree | 529a0221076772b74bac4acb54918b1b79bceb75 /ext/http/http_next.rs | |
parent | 047edf6a75133decf069e6118634caa76a455d7c (diff) |
perf(ext/http): Add a sync phase to http serving (#19321)
Under heavy load, we often have requests queued up that don't need an
async call to retrieve. We can use a fast path sync op to drain this set
of ready requests, and then fall back to the async op once we run out of
work.
This is a .5-1% bump in req/s on an M2 mac. About 90% of the handlers go
through this sync phase (based on a simple instrumentation that is not
included in this PR) and skip the async machinery entirely.
Diffstat (limited to 'ext/http/http_next.rs')
-rw-r--r-- | ext/http/http_next.rs | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/ext/http/http_next.rs b/ext/http/http_next.rs index d479d4a91..7edffed65 100644 --- a/ext/http/http_next.rs +++ b/ext/http/http_next.rs @@ -810,6 +810,30 @@ where )) } +/// Synchronous, non-blocking call to see if there are any further HTTP requests. If anything +/// goes wrong in this method we return [`SlabId::MAX`] and let the async handler pick up the real error. +#[op(fast)] +pub fn op_http_try_wait(state: &mut OpState, rid: ResourceId) -> SlabId { + // The resource needs to exist. + let Ok(join_handle) = state + .resource_table + .get::<HttpJoinHandle>(rid) else { + return SlabId::MAX; + }; + + // If join handle is somehow locked, just abort. + let Some(mut handle) = RcRef::map(&join_handle, |this| &this.2).try_borrow_mut() else { + return SlabId::MAX; + }; + + // See if there are any requests waiting on this channel. If not, return. + let Ok(id) = handle.try_recv() else { + return SlabId::MAX; + }; + + id +} + #[op] pub async fn op_http_wait( state: Rc<RefCell<OpState>>, |