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

use custom headers map; more optimizations

This commit is contained in:
Nikolay Kim
2019-04-06 15:02:02 -07:00
parent 4ef46e26f9
commit 748289f0ff
35 changed files with 668 additions and 180 deletions

View File

@ -5,7 +5,8 @@ use std::rc::Rc;
use bitflags::bitflags;
use crate::extensions::Extensions;
use crate::http::{header, HeaderMap, Method, StatusCode, Uri, Version};
use crate::header::HeaderMap;
use crate::http::{header, Method, StatusCode, Uri, Version};
/// Represents various types of connection
#[derive(Copy, Clone, PartialEq, Debug)]
@ -174,7 +175,7 @@ impl Default for ResponseHead {
ResponseHead {
version: Version::default(),
status: StatusCode::OK,
headers: HeaderMap::with_capacity(16),
headers: HeaderMap::with_capacity(12),
reason: None,
flags: Flags::empty(),
extensions: RefCell::new(Extensions::new()),
@ -182,18 +183,6 @@ impl Default for ResponseHead {
}
}
impl Head for ResponseHead {
fn clear(&mut self) {
self.reason = None;
self.flags = Flags::empty();
self.headers.clear();
}
fn pool() -> &'static MessagePool<Self> {
RESPONSE_POOL.with(|p| *p)
}
}
impl ResponseHead {
/// Message extensions
#[inline]
@ -300,7 +289,6 @@ impl ResponseHead {
pub struct Message<T: Head> {
head: Rc<T>,
pool: &'static MessagePool<T>,
}
impl<T: Head> Message<T> {
@ -314,7 +302,6 @@ impl<T: Head> Clone for Message<T> {
fn clone(&self) -> Self {
Message {
head: self.head.clone(),
pool: self.pool,
}
}
}
@ -336,17 +323,52 @@ impl<T: Head> std::ops::DerefMut for Message<T> {
impl<T: Head> Drop for Message<T> {
fn drop(&mut self) {
if Rc::strong_count(&self.head) == 1 {
self.pool.release(self.head.clone());
T::pool().release(self.head.clone());
}
}
}
pub(crate) struct BoxedResponseHead {
head: Option<Box<ResponseHead>>,
}
impl BoxedResponseHead {
/// Get new message from the pool of objects
pub fn new() -> Self {
RESPONSE_POOL.with(|p| p.get_message())
}
}
impl std::ops::Deref for BoxedResponseHead {
type Target = ResponseHead;
fn deref(&self) -> &Self::Target {
self.head.as_ref().unwrap()
}
}
impl std::ops::DerefMut for BoxedResponseHead {
fn deref_mut(&mut self) -> &mut Self::Target {
self.head.as_mut().unwrap()
}
}
impl Drop for BoxedResponseHead {
fn drop(&mut self) {
RESPONSE_POOL.with(|p| p.release(self.head.take().unwrap()))
}
}
#[doc(hidden)]
/// Request's objects pool
pub struct MessagePool<T: Head>(RefCell<VecDeque<Rc<T>>>);
#[doc(hidden)]
/// Request's objects pool
pub struct BoxedResponsePool(RefCell<VecDeque<Box<ResponseHead>>>);
thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
thread_local!(static RESPONSE_POOL: &'static MessagePool<ResponseHead> = MessagePool::<ResponseHead>::create());
thread_local!(static RESPONSE_POOL: &'static BoxedResponsePool = BoxedResponsePool::create());
impl<T: Head> MessagePool<T> {
fn create() -> &'static MessagePool<T> {
@ -361,14 +383,10 @@ impl<T: Head> MessagePool<T> {
if let Some(r) = Rc::get_mut(&mut msg) {
r.clear();
}
Message {
head: msg,
pool: self,
}
Message { head: msg }
} else {
Message {
head: Rc::new(T::default()),
pool: self,
}
}
}
@ -382,3 +400,34 @@ impl<T: Head> MessagePool<T> {
}
}
}
impl BoxedResponsePool {
fn create() -> &'static BoxedResponsePool {
let pool = BoxedResponsePool(RefCell::new(VecDeque::with_capacity(128)));
Box::leak(Box::new(pool))
}
/// Get message from the pool
#[inline]
fn get_message(&'static self) -> BoxedResponseHead {
if let Some(mut head) = self.0.borrow_mut().pop_front() {
head.reason = None;
head.headers.clear();
head.flags = Flags::empty();
BoxedResponseHead { head: Some(head) }
} else {
BoxedResponseHead {
head: Some(Box::new(ResponseHead::default())),
}
}
}
#[inline]
/// Release request instance
fn release(&self, msg: Box<ResponseHead>) {
let v = &mut self.0.borrow_mut();
if v.len() < 128 {
v.push_front(msg);
}
}
}