test(client): add client benchmarks with mocked IO

This commit is contained in:
Sean McArthur
2019-02-25 14:05:00 -08:00
parent c0e08a41cc
commit 1161479945
2 changed files with 73 additions and 7 deletions

View File

@@ -207,3 +207,66 @@ fn checkout_win_allows_connect_future_to_be_pooled() {
}
}
#[cfg(feature = "nightly")]
#[bench]
fn bench_http1_get_0b(b: &mut test::Bencher) {
let _ = pretty_env_logger::try_init();
let mut rt = Runtime::new().expect("new rt");
let mut connector = MockConnector::new();
let client = Client::builder()
.build::<_, ::Body>(connector.clone());
client.pool.no_timer();
let uri = Uri::from_static("http://mock.local/a");
b.iter(move || {
let sock1 = connector.mock("http://mock.local");
let res1 = client
.get(uri.clone())
.and_then(|res| {
res.into_body().for_each(|_| Ok(()))
});
let srv1 = poll_fn(|| {
try_ready!(sock1.read(&mut [0u8; 512]));
try_ready!(sock1.write(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"));
Ok(Async::Ready(()))
}).map_err(|e: ::std::io::Error| panic!("srv1 poll_fn error: {}", e));
rt.block_on(res1.join(srv1)).expect("res1");
});
}
#[cfg(feature = "nightly")]
#[bench]
fn bench_http1_get_10b(b: &mut test::Bencher) {
let _ = pretty_env_logger::try_init();
let mut rt = Runtime::new().expect("new rt");
let mut connector = MockConnector::new();
let client = Client::builder()
.build::<_, ::Body>(connector.clone());
client.pool.no_timer();
let uri = Uri::from_static("http://mock.local/a");
b.iter(move || {
let sock1 = connector.mock("http://mock.local");
let res1 = client
.get(uri.clone())
.and_then(|res| {
res.into_body().for_each(|_| Ok(()))
});
let srv1 = poll_fn(|| {
try_ready!(sock1.read(&mut [0u8; 512]));
try_ready!(sock1.write(b"HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\n0123456789"));
Ok(Async::Ready(()))
}).map_err(|e: ::std::io::Error| panic!("srv1 poll_fn error: {}", e));
rt.block_on(res1.join(srv1)).expect("res1");
});
}

View File

@@ -438,15 +438,19 @@ impl Drop for DuplexHandle {
type BoxedConnectFut = Box<Future<Item=(Duplex, Connected), Error=io::Error> + Send>;
#[cfg(feature = "runtime")]
#[derive(Clone)]
pub struct MockConnector {
mocks: Mutex<HashMap<String, Vec<BoxedConnectFut>>>,
mocks: Arc<Mutex<MockedConnections>>,
}
#[cfg(feature = "runtime")]
struct MockedConnections(HashMap<String, Vec<BoxedConnectFut>>);
#[cfg(feature = "runtime")]
impl MockConnector {
pub fn new() -> MockConnector {
MockConnector {
mocks: Mutex::new(HashMap::new()),
mocks: Arc::new(Mutex::new(MockedConnections(HashMap::new()))),
}
}
@@ -474,7 +478,7 @@ impl MockConnector {
trace!("MockConnector mocked fut ready");
Ok((duplex, connected))
}));
self.mocks.lock().unwrap().entry(key)
self.mocks.lock().unwrap().0.entry(key)
.or_insert(Vec::new())
.push(fut);
@@ -496,7 +500,7 @@ impl Connect for MockConnector {
"".to_owned()
});
let mut mocks = self.mocks.lock().unwrap();
let mocks = mocks.get_mut(&key)
let mocks = mocks.0.get_mut(&key)
.expect(&format!("unknown mocks uri: {}", key));
assert!(!mocks.is_empty(), "no additional mocks for {}", key);
mocks.remove(0)
@@ -505,11 +509,10 @@ impl Connect for MockConnector {
#[cfg(feature = "runtime")]
impl Drop for MockConnector {
impl Drop for MockedConnections {
fn drop(&mut self) {
if !::std::thread::panicking() {
let mocks = self.mocks.lock().unwrap();
for (key, mocks) in mocks.iter() {
for (key, mocks) in self.0.iter() {
assert_eq!(
mocks.len(),
0,