diff --git a/src/client/tests.rs b/src/client/tests.rs index 17a41943..a9deaac5 100644 --- a/src/client/tests.rs +++ b/src/client/tests.rs @@ -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"); + }); +} diff --git a/src/mock.rs b/src/mock.rs index 492b8c76..6f7cb6d1 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -438,15 +438,19 @@ impl Drop for DuplexHandle { type BoxedConnectFut = Box + Send>; #[cfg(feature = "runtime")] +#[derive(Clone)] pub struct MockConnector { - mocks: Mutex>>, + mocks: Arc>, } +#[cfg(feature = "runtime")] +struct MockedConnections(HashMap>); + #[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,