From dd205fd155b5119bb4e853de636381bbbb915e45 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Feb 2026 20:46:41 +0900 Subject: [PATCH] perf: eliminate recursive call and unnecessary Option (#814) --- actix-service/src/and_then.rs | 22 +++++++++++----------- actix-service/src/apply_cfg.rs | 30 ++++++++++++++++-------------- actix-service/src/then.rs | 22 +++++++++++----------- actix-service/src/transform.rs | 17 +++++++++-------- 4 files changed, 47 insertions(+), 44 deletions(-) diff --git a/actix-service/src/and_then.rs b/actix-service/src/and_then.rs index e453f7be..ee092410 100644 --- a/actix-service/src/and_then.rs +++ b/actix-service/src/and_then.rs @@ -57,7 +57,7 @@ where AndThenServiceResponse { state: State::A { fut: self.0 .0.call(req), - b: Some(self.0.clone()), + b: self.0.clone(), }, } } @@ -84,7 +84,7 @@ pin_project! { A { #[pin] fut: A::Future, - b: Option>, + b: Rc<(A, B)>, }, B { #[pin] @@ -101,17 +101,17 @@ where type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let mut this = self.as_mut().project(); + loop { + let mut this = self.as_mut().project(); - match this.state.as_mut().project() { - StateProj::A { fut, b } => { - let res = ready!(fut.poll(cx))?; - let b = b.take().unwrap(); - let fut = b.1.call(res); - this.state.set(State::B { fut }); - self.poll(cx) + match this.state.as_mut().project() { + StateProj::A { fut, b } => { + let res = ready!(fut.poll(cx))?; + let fut = b.1.call(res); + this.state.set(State::B { fut }); + } + StateProj::B { fut } => return fut.poll(cx), } - StateProj::B { fut } => fut.poll(cx), } } } diff --git a/actix-service/src/apply_cfg.rs b/actix-service/src/apply_cfg.rs index 028fb317..e4086b7e 100644 --- a/actix-service/src/apply_cfg.rs +++ b/actix-service/src/apply_cfg.rs @@ -209,24 +209,26 @@ where type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let mut this = self.as_mut().project(); + loop { + let mut this = self.as_mut().project(); + + match this.state.as_mut().project() { + StateProj::A { fut } => { + let svc = ready!(fut.poll(cx))?; + this.state.set(State::B { svc }); + } + StateProj::B { svc } => { + ready!(svc.poll_ready(cx))?; + + let fut = { + let (_, f) = &**this.store; + f(this.cfg.take().unwrap(), svc) + }; - match this.state.as_mut().project() { - StateProj::A { fut } => { - let svc = ready!(fut.poll(cx))?; - this.state.set(State::B { svc }); - self.poll(cx) - } - StateProj::B { svc } => { - ready!(svc.poll_ready(cx))?; - { - let (_, f) = &**this.store; - let fut = f(this.cfg.take().unwrap(), svc); this.state.set(State::C { fut }); } - self.poll(cx) + StateProj::C { fut } => return fut.poll(cx), } - StateProj::C { fut } => fut.poll(cx), } } } diff --git a/actix-service/src/then.rs b/actix-service/src/then.rs index 09c14a07..24c26f04 100644 --- a/actix-service/src/then.rs +++ b/actix-service/src/then.rs @@ -57,7 +57,7 @@ where ThenServiceResponse { state: State::A { fut: self.0 .0.call(req), - b: Some(self.0.clone()), + b: self.0.clone(), }, } } @@ -81,7 +81,7 @@ pin_project! { A: Service, B: Service>, { - A { #[pin] fut: A::Future, b: Option> }, + A { #[pin] fut: A::Future, b: Rc<(A, B)> }, B { #[pin] fut: B::Future }, } } @@ -94,17 +94,17 @@ where type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let mut this = self.as_mut().project(); + loop { + let mut this = self.as_mut().project(); - match this.state.as_mut().project() { - StateProj::A { fut, b } => { - let res = ready!(fut.poll(cx)); - let b = b.take().unwrap(); - let fut = b.1.call(res); - this.state.set(State::B { fut }); - self.poll(cx) + match this.state.as_mut().project() { + StateProj::A { fut, b } => { + let res = ready!(fut.poll(cx)); + let fut = b.1.call(res); + this.state.set(State::B { fut }); + } + StateProj::B { fut } => return fut.poll(cx), } - StateProj::B { fut } => fut.poll(cx), } } } diff --git a/actix-service/src/transform.rs b/actix-service/src/transform.rs index 98ad7a07..c31dae79 100644 --- a/actix-service/src/transform.rs +++ b/actix-service/src/transform.rs @@ -205,16 +205,17 @@ where type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let mut this = self.as_mut().project(); + loop { + let mut this = self.as_mut().project(); - match this.state.as_mut().project() { - ApplyTransformFutureStateProj::A { fut } => { - let srv = ready!(fut.poll(cx))?; - let fut = this.store.0.new_transform(srv); - this.state.set(ApplyTransformFutureState::B { fut }); - self.poll(cx) + match this.state.as_mut().project() { + ApplyTransformFutureStateProj::A { fut } => { + let srv = ready!(fut.poll(cx))?; + let fut = this.store.0.new_transform(srv); + this.state.set(ApplyTransformFutureState::B { fut }); + } + ApplyTransformFutureStateProj::B { fut } => return fut.poll(cx), } - ApplyTransformFutureStateProj::B { fut } => fut.poll(cx), } } }