From d54925456d6afb2f26866f98d9a937390b71f11a Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Mon, 22 Jun 2026 04:07:41 +0300 Subject: [PATCH 1/2] perf(router): avoid path-param allocs on fast paths --- oxyroute/streaming.py | 17 ++++++++++------- src/state.rs | 14 +++++++------- src/websocket.rs | 5 ++--- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/oxyroute/streaming.py b/oxyroute/streaming.py index 85af591..67ef632 100644 --- a/oxyroute/streaming.py +++ b/oxyroute/streaming.py @@ -8,13 +8,16 @@ class _StreamDone: - __slots__ = () + __slots__ = ("status",) __oxyroute_stream_done__ = True + def __init__(self, status: int = 200) -> None: + self.status = status -def stream_done() -> Any: + +def stream_done(status: int = 200) -> Any: """Return a marker value telling OxyRoute the response was already sent.""" - return _StreamDone() + return _StreamDone(status) async def stream_bytes( @@ -44,7 +47,7 @@ async def stream_bytes( else: for chunk in iterable: # type: ignore[not-an-iterable] await stream.send_bytes(chunk) - return stream_done() + return stream_done(status) # Fallback for test/ASGI transports chunks: list[bytes] = [] @@ -55,7 +58,7 @@ async def stream_bytes( for chunk in iterable: # type: ignore[not-an-iterable] chunks.append(chunk) protocol.response_bytes(status, base_headers, b"".join(chunks)) - return stream_done() + return stream_done(status) async def stream_text( @@ -85,7 +88,7 @@ async def stream_text( else: for chunk in iterable: # type: ignore[not-an-iterable] await stream.send_str(chunk) - return stream_done() + return stream_done(status) chunks: list[str] = [] if hasattr(iterable, "__aiter__"): @@ -95,7 +98,7 @@ async def stream_text( for chunk in iterable: # type: ignore[not-an-iterable] chunks.append(chunk) protocol.response_str(status, base_headers, "".join(chunks)) - return stream_done() + return stream_done(status) async def stream_jsonl( diff --git a/src/state.rs b/src/state.rs index 85362ac..c2b9166 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::sync::Arc; use matchit::Router; @@ -200,11 +200,11 @@ pub struct HotSnapshot { pub fn match_ws_route_compiled( compiled: &CompiledRouters, path: &str, -) -> Option<(usize, HashMap)> { +) -> Option<(usize, Vec<(String, String)>)> { compiled.websocket.at(path).ok().map(|m| { - let mut pmap = HashMap::new(); + let mut pmap = Vec::new(); for (k, v) in m.params.iter() { - pmap.insert(k.to_string(), v.to_string()); + pmap.push((k.to_string(), v.to_string())); } (*m.value, pmap) }) @@ -217,12 +217,12 @@ pub fn match_route_compiled( compiled: &CompiledRouters, method: &str, path: &str, -) -> Option)>> { +) -> Option)>> { let g = router_for_compiled(compiled, method)?; Some(g.at(path).ok().map(|m| { - let mut pmap = HashMap::new(); + let mut pmap = Vec::new(); for (k, v) in m.params.iter() { - pmap.insert(k.to_string(), v.to_string()); + pmap.push((k.to_string(), v.to_string())); } (*m.value, pmap) })) diff --git a/src/websocket.rs b/src/websocket.rs index ad66fde..e746472 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -7,7 +7,6 @@ //! it would have awaited natively — no extra Tokio future bridge, no scheduling cost. //! //! [1]: https://github.com/emmett-framework/granian — see `granian/rsgi.py`. -use std::collections::HashMap; use std::sync::Arc; use parking_lot::Mutex; @@ -30,7 +29,7 @@ pub struct WebSocket { protocol: Py, scope: Py, transport: Arc>>>, - path_params: HashMap, + path_params: Vec<(String, String)>, closed: Arc>, } @@ -38,7 +37,7 @@ impl WebSocket { pub fn new( protocol: Py, scope: Py, - path_params: HashMap, + path_params: Vec<(String, String)>, ) -> Self { Self { protocol, From fd96fe35b08dcca924105da3e268c1bb641bb305 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Mon, 22 Jun 2026 04:11:33 +0300 Subject: [PATCH 2/2] style: format rust files --- src/websocket.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/websocket.rs b/src/websocket.rs index e746472..597fda4 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -34,11 +34,7 @@ pub struct WebSocket { } impl WebSocket { - pub fn new( - protocol: Py, - scope: Py, - path_params: Vec<(String, String)>, - ) -> Self { + pub fn new(protocol: Py, scope: Py, path_params: Vec<(String, String)>) -> Self { Self { protocol, scope,