1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-08-29 00:07:48 +02:00

use objects pool for HttpRequest; optimize nested services call

This commit is contained in:
Nikolay Kim
2019-04-07 23:06:21 -07:00
parent 75b213a6f0
commit aa78565453
20 changed files with 343 additions and 295 deletions

View File

@@ -1,4 +1,4 @@
use std::cell::{Ref, RefMut};
use std::cell::{Ref, RefCell, RefMut};
use std::fmt;
use std::rc::Rc;
@@ -15,29 +15,34 @@ use crate::rmap::ResourceMap;
#[derive(Clone)]
/// An HTTP Request
pub struct HttpRequest {
pub struct HttpRequest(pub(crate) Rc<HttpRequestInner>);
pub(crate) struct HttpRequestInner {
pub(crate) head: Message<RequestHead>,
pub(crate) path: Path<Url>,
rmap: Rc<ResourceMap>,
config: AppConfig,
route_data: Option<Rc<Extensions>>,
pool: &'static HttpRequestPool,
}
impl HttpRequest {
#[inline]
pub(crate) fn new(
head: Message<RequestHead>,
path: Path<Url>,
head: Message<RequestHead>,
rmap: Rc<ResourceMap>,
config: AppConfig,
pool: &'static HttpRequestPool,
) -> HttpRequest {
HttpRequest {
HttpRequest(Rc::new(HttpRequestInner {
head,
path,
rmap,
config,
pool,
route_data: None,
}
}))
}
}
@@ -45,7 +50,14 @@ impl HttpRequest {
/// This method returns reference to the request head
#[inline]
pub fn head(&self) -> &RequestHead {
&self.head
&self.0.head
}
/// This method returns muttable reference to the request head.
/// panics if multiple references of http request exists.
#[inline]
pub(crate) fn head_mut(&mut self) -> &mut RequestHead {
&mut Rc::get_mut(&mut self.0).unwrap().head
}
/// Request's uri.
@@ -98,7 +110,12 @@ impl HttpRequest {
/// access the matched value for that segment.
#[inline]
pub fn match_info(&self) -> &Path<Url> {
&self.path
&self.0.path
}
#[inline]
pub(crate) fn match_info_mut(&mut self) -> &mut Path<Url> {
&mut Rc::get_mut(&mut self.0).unwrap().path
}
/// Request extensions
@@ -141,7 +158,7 @@ impl HttpRequest {
U: IntoIterator<Item = I>,
I: AsRef<str>,
{
self.rmap.url_for(&self, name, elements)
self.0.rmap.url_for(&self, name, elements)
}
/// Generate url for named resource
@@ -162,13 +179,13 @@ impl HttpRequest {
/// App config
#[inline]
pub fn app_config(&self) -> &AppConfig {
&self.config
&self.0.config
}
/// Get an application data stored with `App::data()` method during
/// application configuration.
pub fn app_data<T: 'static>(&self) -> Option<Data<T>> {
if let Some(st) = self.config.extensions().get::<Data<T>>() {
if let Some(st) = self.0.config.extensions().get::<Data<T>>() {
Some(st.clone())
} else {
None
@@ -178,7 +195,7 @@ impl HttpRequest {
/// Load route data. Route data could be set during
/// route configuration with `Route::data()` method.
pub fn route_data<T: 'static>(&self) -> Option<&RouteData<T>> {
if let Some(ref ext) = self.route_data {
if let Some(ref ext) = self.0.route_data {
ext.get::<RouteData<T>>()
} else {
None
@@ -186,7 +203,7 @@ impl HttpRequest {
}
pub(crate) fn set_route_data(&mut self, data: Option<Rc<Extensions>>) {
self.route_data = data;
Rc::get_mut(&mut self.0).unwrap().route_data = data;
}
}
@@ -202,13 +219,13 @@ impl HttpMessage for HttpRequest {
/// Request extensions
#[inline]
fn extensions(&self) -> Ref<Extensions> {
self.head.extensions()
self.0.head.extensions()
}
/// Mutable reference to a the request's extensions
#[inline]
fn extensions_mut(&self) -> RefMut<Extensions> {
self.head.extensions_mut()
self.0.head.extensions_mut()
}
#[inline]
@@ -217,6 +234,17 @@ impl HttpMessage for HttpRequest {
}
}
impl Drop for HttpRequest {
fn drop(&mut self) {
if Rc::strong_count(&self.0) == 1 {
let v = &mut self.0.pool.0.borrow_mut();
if v.len() < 128 {
v.push(self.0.clone());
}
}
}
}
/// It is possible to get `HttpRequest` as an extractor handler parameter
///
/// ## Example
@@ -252,8 +280,8 @@ impl fmt::Debug for HttpRequest {
writeln!(
f,
"\nHttpRequest {:?} {}:{}",
self.head.version,
self.head.method,
self.0.head.version,
self.0.head.method,
self.path()
)?;
if !self.query_string().is_empty() {
@@ -270,6 +298,26 @@ impl fmt::Debug for HttpRequest {
}
}
/// Request's objects pool
pub(crate) struct HttpRequestPool(RefCell<Vec<Rc<HttpRequestInner>>>);
impl HttpRequestPool {
pub(crate) fn create() -> &'static HttpRequestPool {
let pool = HttpRequestPool(RefCell::new(Vec::with_capacity(128)));
Box::leak(Box::new(pool))
}
/// Get message from the pool
#[inline]
pub(crate) fn get_request(&self) -> Option<HttpRequest> {
if let Some(inner) = self.0.borrow_mut().pop() {
Some(HttpRequest(inner))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;