perf(http2): eagerly poll some futures in h2 dispatchers before allocating in executor

This commit is contained in:
Sean McArthur
2018-10-24 15:04:30 -07:00
parent dcf0347151
commit 94e02ac276
3 changed files with 85 additions and 49 deletions

View File

@@ -122,14 +122,22 @@ where
}
};
if !eos {
let conn_drop_ref = conn_dropper.clone();
let pipe = PipeToSendStream::new(body, body_tx)
.map_err(|e| debug!("client request body error: {}", e))
.then(move |x| {
drop(conn_drop_ref);
x
});
self.executor.execute(pipe)?;
let mut pipe = PipeToSendStream::new(body, body_tx)
.map_err(|e| debug!("client request body error: {}", e));
// eagerly see if the body pipe is ready and
// can thus skip allocating in the executor
match pipe.poll() {
Ok(Async::Ready(())) | Err(()) => (),
Ok(Async::NotReady) => {
let conn_drop_ref = conn_dropper.clone();
let pipe = pipe.then(move |x| {
drop(conn_drop_ref);
x
});
self.executor.execute(pipe)?;
}
}
}
let fut = fut

View File

@@ -5,6 +5,7 @@ use tokio_io::{AsyncRead, AsyncWrite};
use ::headers::content_length_parse_all;
use ::body::Payload;
use body::internal::FullDataArg;
use ::common::exec::H2Exec;
use ::headers;
use ::service::Service;
@@ -133,8 +134,16 @@ where
let req = req.map(|stream| {
::Body::h2(stream, content_length)
});
let fut = H2Stream::new(service.call(req), respond);
exec.execute_h2stream(fut)?;
let mut fut = H2Stream::new(service.call(req), respond);
// try to eagerly poll the future, so that we might
// not need to allocate a new task...
match fut.poll() {
Ok(Async::Ready(())) | Err(()) => (),
Ok(Async::NotReady) => {
exec.execute_h2stream(fut)?;
}
}
}
// no more incoming streams...
@@ -193,7 +202,7 @@ where
Err(e) => return Err(::Error::new_user_service(e)),
};
let (head, body) = res.into_parts();
let (head, mut body) = res.into_parts();
let mut res = ::http::Response::from_parts(head, ());
super::strip_connection_headers(res.headers_mut(), false);
@@ -204,10 +213,6 @@ where
.expect("DATE is a valid HeaderName")
.or_insert_with(::proto::h1::date::update_and_header_value);
// automatically set Content-Length from body...
if let Some(len) = body.content_length() {
headers::set_content_length_if_missing(res.headers_mut(), len);
}
macro_rules! reply {
($eos:expr) => ({
match self.reply.send_response(res, $eos) {
@@ -220,6 +225,20 @@ where
}
})
}
if let Some(full) = body.__hyper_full_data(FullDataArg(())).0 {
let mut body_tx = reply!(false);
let buf = SendBuf(Some(full));
body_tx
.send_data(buf, true)
.map_err(::Error::new_body_write)?;
return Ok(Async::Ready(()));
}
// automatically set Content-Length from body...
if let Some(len) = body.content_length() {
headers::set_content_length_if_missing(res.headers_mut(), len);
}
if !body.is_end_stream() {
let body_tx = reply!(false);
H2StreamState::Body(PipeToSendStream::new(body, body_tx))