From 59272563b4e4bd289ccb33b4c0a0f6ce3296c83b Mon Sep 17 00:00:00 2001 From: kanarus Date: Thu, 22 Aug 2024 03:01:12 +0900 Subject: [PATCH] perf: reuse `Request` in a session (#249) * reuse Request in session * session: not call explicit shutdown * remove unnecessary 'static * refactor to make clear `req` lifecycle * refactor `req.clear` aand its position --- ohkami/src/header/map.rs | 7 +++++++ ohkami/src/request/headers.rs | 9 +++++++++ ohkami/src/request/memory.rs | 6 ++++++ ohkami/src/request/mod.rs | 14 ++++++++++++++ ohkami/src/response/mod.rs | 2 +- ohkami/src/session/mod.rs | 30 +++++++++--------------------- 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/ohkami/src/header/map.rs b/ohkami/src/header/map.rs index 4d23b8a3..58f1fce6 100644 --- a/ohkami/src/header/map.rs +++ b/ohkami/src/header/map.rs @@ -14,6 +14,13 @@ impl IndexMap { } } + #[cfg(any(feature="rt_tokio",feature="rt_async-std"))] + #[inline] + pub(crate) fn clear(&mut self) { + for idx in &mut self.index {*idx = Self::NULL} + self.values.clear(); + } + #[inline(always)] pub(crate) unsafe fn get(&self, index: usize) -> Option<&Value> { match *self.index.get_unchecked(index) { diff --git a/ohkami/src/request/headers.rs b/ohkami/src/request/headers.rs index 109ad5b9..627a302b 100644 --- a/ohkami/src/request/headers.rs +++ b/ohkami/src/request/headers.rs @@ -359,6 +359,15 @@ impl Headers { Self::init() } + #[cfg(any(feature="rt_tokio",feature="rt_async-std"))] + #[inline] + pub(crate) fn clear(&mut self) { + self.standard.clear(); + if let Some(map) = &mut self.custom { + map.clear() + } + } + #[inline] pub(crate) fn get_raw(&self, name: Header) -> Option<&CowSlice> { unsafe {self.standard.get(name as usize)} } diff --git a/ohkami/src/request/memory.rs b/ohkami/src/request/memory.rs index 64e3b1a8..9e228fbd 100644 --- a/ohkami/src/request/memory.rs +++ b/ohkami/src/request/memory.rs @@ -33,6 +33,12 @@ impl Store { pub(super) const fn init() -> Self { Self(None) } + #[cfg(any(feature="rt_tokio",feature="rt_async-std"))] + pub(super) fn clear(&mut self) { + if let Some(map) = &mut self.0 { + map.clear() + } + } #[inline] pub fn insert(&mut self, value: Data) { self.0.get_or_insert_with(|| Box::new(HashMap::default())) diff --git a/ohkami/src/request/mod.rs b/ohkami/src/request/mod.rs index 1aa4c466..0209b053 100644 --- a/ohkami/src/request/mod.rs +++ b/ohkami/src/request/mod.rs @@ -186,6 +186,20 @@ impl Request { store: Store::init(), } } + #[cfg(any(feature="rt_tokio",feature="rt_async-std"))] + #[inline] + pub(crate) fn clear(&mut self) { + if self.__buf__[0] != 0 { + for b in &mut *self.__buf__ { + match b {0 => break, _ => *b = 0} + } + self.path = Path::uninit(); + self.query = None; + self.headers.clear(); + self.payload = None; + self.store.clear(); + } /* else: just after `init`ed or `clear`ed */ + } #[cfg(any(feature="rt_tokio",feature="rt_async-std"))] #[inline] diff --git a/ohkami/src/response/mod.rs b/ohkami/src/response/mod.rs index aca7d11b..457f95b2 100644 --- a/ohkami/src/response/mod.rs +++ b/ohkami/src/response/mod.rs @@ -172,7 +172,7 @@ impl Upgrade { impl Response { #[cfg_attr(not(feature="sse"), inline)] pub(crate) async fn send(mut self, - conn: &mut (impl AsyncWriter + Unpin + 'static) + conn: &mut (impl AsyncWriter + Unpin) ) -> Upgrade { self.complete(); diff --git a/ohkami/src/session/mod.rs b/ohkami/src/session/mod.rs index bfb1a77d..4b31c375 100644 --- a/ohkami/src/session/mod.rs +++ b/ohkami/src/session/mod.rs @@ -64,45 +64,33 @@ impl Session { } match timeout_in(Duration::from_secs(env::OHKAMI_KEEPALIVE_TIMEOUT()), async { + let mut req = Request::init(); + let mut req = unsafe {Pin::new_unchecked(&mut req)}; loop { - let mut req = Request::init(); - let mut req = unsafe {Pin::new_unchecked(&mut req)}; + req.clear(); match req.as_mut().read(&mut self.connection).await { Ok(Some(())) => { let close = matches!(req.headers.Connection(), Some("close" | "Close")); - let res = match catch_unwind(AssertUnwindSafe(|| self.router.handle(req.get_mut()))) { + let res = match catch_unwind(AssertUnwindSafe({ + let req = req.as_mut(); + || self.router.handle(req.get_mut()) + })) { Ok(future) => future.await, Err(panic) => panicking(panic), }; let upgrade = res.send(&mut self.connection).await; - if !upgrade.is_none() { - break upgrade - } + if !upgrade.is_none() {break upgrade} if close {break Upgrade::None} } Ok(None) => break Upgrade::None, Err(res) => {res.send(&mut self.connection).await;}, - }; + } } }).await { Some(Upgrade::None) | None => { crate::DEBUG!("about to shutdown connection"); - - if let Some(err) = { - #[cfg(feature="rt_tokio")] {use crate::__rt__::AsyncWriter; - self.connection.shutdown().await - } - #[cfg(feature="rt_async-std")] { - self.connection.shutdown(std::net::Shutdown::Both) - } - }.err() { - match err.kind() { - std::io::ErrorKind::NotConnected => (), - _ => panic!("Failed to shutdown stream: {err}") - } - } } #[cfg(all(feature="ws", any(feature="rt_tokio",feature="rt_async-std")))]