From 810435f1469eb028c6a819368d63edb54d6c341c Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Mon, 4 Jun 2018 10:59:07 -0700 Subject: [PATCH] feat(server): add `http1_writev` config option for servers Closes #1527 --- src/proto/h1/io.rs | 9 ++++----- src/server/conn.rs | 19 +++++++++++++++++++ src/server/mod.rs | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/proto/h1/io.rs b/src/proto/h1/io.rs index 115b074c04..d0a953c7c3 100644 --- a/src/proto/h1/io.rs +++ b/src/proto/h1/io.rs @@ -66,12 +66,11 @@ where } pub fn set_flush_pipeline(&mut self, enabled: bool) { + debug_assert!(!self.write_buf.has_remaining()); self.flush_pipeline = enabled; - self.write_buf.set_strategy(if enabled { - Strategy::Flatten - } else { - Strategy::Auto - }); + if enabled { + self.set_write_strategy_flatten(); + } } pub fn set_max_buf_size(&mut self, max: usize) { diff --git a/src/server/conn.rs b/src/server/conn.rs index 9bcffe20d4..45e0d277d3 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -37,6 +37,7 @@ use error::{Kind, Parse}; #[derive(Clone, Debug)] pub struct Http { exec: Exec, + h1_writev: bool, mode: ConnectionMode, keep_alive: bool, max_buf_size: Option, @@ -138,6 +139,7 @@ impl Http { pub fn new() -> Http { Http { exec: Exec::Default, + h1_writev: true, mode: ConnectionMode::Fallback, keep_alive: true, max_buf_size: None, @@ -157,6 +159,20 @@ impl Http { self } + /// Set whether HTTP/1 connections should try to use vectored writes, + /// or always flatten into a single buffer. + /// + /// Note that setting this to false may mean more copies of body data, + /// but may also improve performance when an IO transport doesn't + /// support vectored writes well, such as most TLS implementations. + /// + /// Default is `true`. + #[inline] + pub fn http1_writev(&mut self, val: bool) -> &mut Self { + self.h1_writev = val; + self + } + /// Sets whether HTTP2 is required. /// /// Default is false @@ -264,6 +280,9 @@ impl Http { if !self.keep_alive { conn.disable_keep_alive(); } + if !self.h1_writev { + conn.set_write_strategy_flatten(); + } conn.set_flush_pipeline(self.pipeline_flush); if let Some(max) = self.max_buf_size { conn.set_max_buf_size(max); diff --git a/src/server/mod.rs b/src/server/mod.rs index 924deaf8a0..33898c587d 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -175,6 +175,21 @@ impl Builder { self } + /// Set whether HTTP/1 connections should try to use vectored writes, + /// or always flatten into a single buffer. + /// + /// # Note + /// + /// Setting this to `false` may mean more copies of body data, + /// but may also improve performance when an IO transport doesn't + /// support vectored writes well, such as most TLS implementations. + /// + /// Default is `true`. + pub fn http1_writev(mut self, val: bool) -> Self { + self.protocol.http1_writev(val); + self + } + /// Sets whether HTTP/2 is required. /// /// Default is `false`.