mirror of
https://github.com/actix/actix-extras.git
synced 2025-06-30 20:04:26 +02:00
optimize http message serialization
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
use std::io;
|
||||
use std::{io, mem};
|
||||
use bytes::BufMut;
|
||||
use futures::{Async, Poll};
|
||||
use tokio_io::AsyncWrite;
|
||||
@ -135,38 +135,60 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
|
||||
|
||||
// status line
|
||||
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 {
|
||||
Body::Empty =>
|
||||
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 {
|
||||
buffer.extend_from_slice(b"\r\n");
|
||||
SharedBytes::extend_from_slice_(buffer, b"\r\n");
|
||||
},
|
||||
Body::Binary(ref bytes) =>
|
||||
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
|
||||
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() {
|
||||
let v = value.as_ref();
|
||||
let k = key.as_str().as_bytes();
|
||||
buffer.reserve(k.len() + v.len() + 4);
|
||||
buffer.put_slice(k);
|
||||
buffer.put_slice(b": ");
|
||||
buffer.put_slice(v);
|
||||
buffer.put_slice(b"\r\n");
|
||||
let len = k.len() + v.len() + 4;
|
||||
if len > remaining {
|
||||
unsafe{buffer.advance_mut(pos)};
|
||||
pos = 0;
|
||||
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
|
||||
if !msg.headers().contains_key(DATE) {
|
||||
helpers::date(&mut buffer);
|
||||
} else {
|
||||
// msg eof
|
||||
buffer.extend_from_slice(b"\r\n");
|
||||
SharedBytes::extend_from_slice_(buffer, b"\r\n");
|
||||
}
|
||||
self.headers_size = buffer.len() as u32;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use std::mem;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::collections::VecDeque;
|
||||
use bytes::BytesMut;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
|
||||
use body::Binary;
|
||||
|
||||
@ -98,12 +98,32 @@ impl SharedBytes {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
|
||||
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]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user