mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 16:02:59 +01:00
optimize http message serialization
This commit is contained in:
parent
4d81186059
commit
6ee14efbe2
@ -74,6 +74,7 @@ impl SharedMessagePool {
|
|||||||
SharedMessagePool(RefCell::new(VecDeque::with_capacity(128)))
|
SharedMessagePool(RefCell::new(VecDeque::with_capacity(128)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get(&self) -> Rc<HttpMessage> {
|
pub fn get(&self) -> Rc<HttpMessage> {
|
||||||
if let Some(msg) = self.0.borrow_mut().pop_front() {
|
if let Some(msg) = self.0.borrow_mut().pop_front() {
|
||||||
msg
|
msg
|
||||||
@ -82,6 +83,7 @@ impl SharedMessagePool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn release(&self, mut msg: Rc<HttpMessage>) {
|
pub fn release(&self, mut msg: Rc<HttpMessage>) {
|
||||||
let v = &mut self.0.borrow_mut();
|
let v = &mut self.0.borrow_mut();
|
||||||
if v.len() < 128 {
|
if v.len() < 128 {
|
||||||
|
@ -21,6 +21,7 @@ struct Inner {
|
|||||||
named: HashMap<String, (Pattern, bool)>,
|
named: HashMap<String, (Pattern, bool)>,
|
||||||
patterns: Vec<Pattern>,
|
patterns: Vec<Pattern>,
|
||||||
srv: ServerSettings,
|
srv: ServerSettings,
|
||||||
|
hasroutes: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Router {
|
impl Router {
|
||||||
@ -55,6 +56,7 @@ impl Router {
|
|||||||
regset: RegexSet::new(&paths).unwrap(),
|
regset: RegexSet::new(&paths).unwrap(),
|
||||||
named: named,
|
named: named,
|
||||||
patterns: patterns,
|
patterns: patterns,
|
||||||
|
hasroutes: !paths.is_empty(),
|
||||||
srv: settings })), resources)
|
srv: settings })), resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +74,7 @@ impl Router {
|
|||||||
|
|
||||||
/// Query for matched resource
|
/// Query for matched resource
|
||||||
pub fn recognize<S>(&self, req: &mut HttpRequest<S>) -> Option<usize> {
|
pub fn recognize<S>(&self, req: &mut HttpRequest<S>) -> Option<usize> {
|
||||||
|
if !self.0.hasroutes { return None }
|
||||||
let mut idx = None;
|
let mut idx = None;
|
||||||
{
|
{
|
||||||
if self.0.prefix_len > req.path().len() {
|
if self.0.prefix_len > req.path().len() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::io;
|
use std::{io, mem};
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
use futures::{Async, Poll};
|
use futures::{Async, Poll};
|
||||||
use tokio_io::AsyncWrite;
|
use tokio_io::AsyncWrite;
|
||||||
@ -135,38 +135,60 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
|
|||||||
|
|
||||||
// status line
|
// status line
|
||||||
helpers::write_status_line(version, msg.status().as_u16(), &mut buffer);
|
helpers::write_status_line(version, msg.status().as_u16(), &mut buffer);
|
||||||
buffer.extend_from_slice(msg.reason().as_bytes());
|
SharedBytes::extend_from_slice_(buffer, msg.reason().as_bytes());
|
||||||
|
|
||||||
match body {
|
match body {
|
||||||
Body::Empty =>
|
Body::Empty =>
|
||||||
if req.method != Method::HEAD {
|
if req.method != Method::HEAD {
|
||||||
buffer.extend_from_slice(b"\r\ncontent-length: 0\r\n");
|
SharedBytes::extend_from_slice_(buffer, b"\r\ncontent-length: 0\r\n");
|
||||||
} else {
|
} else {
|
||||||
buffer.extend_from_slice(b"\r\n");
|
SharedBytes::extend_from_slice_(buffer, b"\r\n");
|
||||||
},
|
},
|
||||||
Body::Binary(ref bytes) =>
|
Body::Binary(ref bytes) =>
|
||||||
helpers::write_content_length(bytes.len(), &mut buffer),
|
helpers::write_content_length(bytes.len(), &mut buffer),
|
||||||
_ =>
|
_ =>
|
||||||
buffer.extend_from_slice(b"\r\n"),
|
SharedBytes::extend_from_slice_(buffer, b"\r\n"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// write headers
|
// write headers
|
||||||
|
let mut pos = 0;
|
||||||
|
let mut remaining = buffer.remaining_mut();
|
||||||
|
let mut buf: &mut [u8] = unsafe{ mem::transmute(buffer.bytes_mut()) };
|
||||||
for (key, value) in msg.headers() {
|
for (key, value) in msg.headers() {
|
||||||
let v = value.as_ref();
|
let v = value.as_ref();
|
||||||
let k = key.as_str().as_bytes();
|
let k = key.as_str().as_bytes();
|
||||||
buffer.reserve(k.len() + v.len() + 4);
|
let len = k.len() + v.len() + 4;
|
||||||
buffer.put_slice(k);
|
if len > remaining {
|
||||||
buffer.put_slice(b": ");
|
unsafe{buffer.advance_mut(pos)};
|
||||||
buffer.put_slice(v);
|
pos = 0;
|
||||||
buffer.put_slice(b"\r\n");
|
buffer.reserve(len);
|
||||||
|
remaining = buffer.remaining_mut();
|
||||||
|
buf = unsafe{ mem::transmute(buffer.bytes_mut()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[pos..pos+k.len()].copy_from_slice(k);
|
||||||
|
pos += k.len();
|
||||||
|
buf[pos..pos+2].copy_from_slice(b": ");
|
||||||
|
pos += 2;
|
||||||
|
buf[pos..pos+v.len()].copy_from_slice(v);
|
||||||
|
pos += v.len();
|
||||||
|
buf[pos..pos+2].copy_from_slice(b"\r\n");
|
||||||
|
pos += 2;
|
||||||
|
remaining -= len;
|
||||||
|
|
||||||
|
//buffer.put_slice(k);
|
||||||
|
//buffer.put_slice(b": ");
|
||||||
|
//buffer.put_slice(v);
|
||||||
|
//buffer.put_slice(b"\r\n");
|
||||||
}
|
}
|
||||||
|
unsafe{buffer.advance_mut(pos)};
|
||||||
|
|
||||||
// using helpers::date is quite a lot faster
|
// using helpers::date is quite a lot faster
|
||||||
if !msg.headers().contains_key(DATE) {
|
if !msg.headers().contains_key(DATE) {
|
||||||
helpers::date(&mut buffer);
|
helpers::date(&mut buffer);
|
||||||
} else {
|
} else {
|
||||||
// msg eof
|
// msg eof
|
||||||
buffer.extend_from_slice(b"\r\n");
|
SharedBytes::extend_from_slice_(buffer, b"\r\n");
|
||||||
}
|
}
|
||||||
self.headers_size = buffer.len() as u32;
|
self.headers_size = buffer.len() as u32;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::mem;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use bytes::BytesMut;
|
use bytes::{BufMut, BytesMut};
|
||||||
|
|
||||||
use body::Binary;
|
use body::Binary;
|
||||||
|
|
||||||
@ -98,12 +98,32 @@ impl SharedBytes {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
|
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
|
||||||
pub fn extend(&self, data: Binary) {
|
pub fn extend(&self, data: Binary) {
|
||||||
self.get_mut().extend_from_slice(data.as_ref());
|
let buf = self.get_mut();
|
||||||
|
let data = data.as_ref();
|
||||||
|
buf.reserve(data.len());
|
||||||
|
SharedBytes::put_slice(buf, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extend_from_slice(&self, data: &[u8]) {
|
pub fn extend_from_slice(&self, data: &[u8]) {
|
||||||
self.get_mut().extend_from_slice(data);
|
let buf = self.get_mut();
|
||||||
|
buf.reserve(data.len());
|
||||||
|
SharedBytes::put_slice(buf, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn put_slice(buf: &mut BytesMut, src: &[u8]) {
|
||||||
|
let len = src.len();
|
||||||
|
unsafe {
|
||||||
|
buf.bytes_mut()[..len].copy_from_slice(src);
|
||||||
|
buf.advance_mut(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn extend_from_slice_(buf: &mut BytesMut, data: &[u8]) {
|
||||||
|
buf.reserve(data.len());
|
||||||
|
SharedBytes::put_slice(buf, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user