From ee8fcfbdc03cb862fa1f1995b47c7178339ef1d6 Mon Sep 17 00:00:00 2001 From: "Stephen M. Coakley" Date: Mon, 19 Aug 2019 21:22:20 -0500 Subject: [PATCH] Fix benchmark compilation --- .editorconfig | 3 ++ Makefile | 12 ++++++++ benchmarks/Cargo.toml | 10 +++---- benchmarks/benches/download.rs | 29 +++++++++--------- benchmarks/src/lib.rs | 55 ++++++++++++++++++++++++++++++++++ src/agent.rs | 13 ++++++-- 6 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 Makefile create mode 100644 benchmarks/src/lib.rs diff --git a/.editorconfig b/.editorconfig index 77af2e01..db939803 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ insert_final_newline = true [*.{yaml,yml}] indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..ae4a5405 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: build +build: + cargo build + +.PHONY: test +test: + cargo test + +.PHONY: bench +bench: + cargo bench -p isahc-benchmarks + diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index 3760e9f3..e5bdbbf2 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -4,16 +4,16 @@ version = "0.0.0" edition = "2018" publish = false -[dependencies.isahc] -path = ".." - -[dev-dependencies] +[dependencies] criterion = "0.2" -env_logger = "0.6" +curl = "0.4" rayon = "1" reqwest = "0.9" rouille = "3" +[dependencies.isahc] +path = ".." + [[bench]] name = "download" harness = false diff --git a/benchmarks/benches/download.rs b/benchmarks/benches/download.rs index b83890cc..c488e605 100644 --- a/benchmarks/benches/download.rs +++ b/benchmarks/benches/download.rs @@ -1,13 +1,14 @@ //! Benchmark for downloading files over localhost. use criterion::*; -use utilities::server; +use isahc_benchmarks::TestServer; +use std::io::{Write, sink}; static DATA: [u8; 0x10000] = [1; 0x10000]; // 64K fn benchmark(c: &mut Criterion) { c.bench_function("download 64K: curl", move |b| { - let server = server::spawn(|_| server::static_response(&DATA)); + let server = TestServer::static_response(&DATA); let endpoint = server.endpoint(); b.iter_batched( @@ -17,12 +18,12 @@ fn benchmark(c: &mut Criterion) { easy }, |mut easy| { - let mut body = Vec::new(); + let mut sink = sink(); let mut transfer = easy.transfer(); transfer .write_function(|bytes| { - body.extend_from_slice(bytes); + sink.write_all(bytes).unwrap(); Ok(bytes.len()) }) .unwrap(); @@ -34,37 +35,35 @@ fn benchmark(c: &mut Criterion) { }); c.bench_function("download 64K: isahc", move |b| { - use std::io::Read; + use isahc::prelude::*; - let server = server::spawn(|_| server::static_response(&DATA)); + let server = TestServer::static_response(&DATA); let endpoint = server.endpoint(); b.iter_batched( - || isahc::Client::new(), + || isahc::HttpClient::new().unwrap(), |client| { - let mut body = Vec::new(); - - let mut response = client.get(&endpoint).unwrap(); - response.body_mut().read_to_end(&mut body).unwrap(); + client.get(&endpoint) + .unwrap() + .copy_to(sink()) + .unwrap(); }, BatchSize::SmallInput, ) }); c.bench_function("download 64K: reqwest", move |b| { - let server = server::spawn(|_| server::static_response(&DATA)); + let server = TestServer::static_response(&DATA); let endpoint = server.endpoint(); b.iter_batched( || reqwest::Client::new(), |client| { - let mut body = Vec::new(); - client .get(&endpoint) .send() .unwrap() - .copy_to(&mut body) + .copy_to(&mut sink()) .unwrap(); }, BatchSize::SmallInput, diff --git a/benchmarks/src/lib.rs b/benchmarks/src/lib.rs new file mode 100644 index 00000000..c75bb427 --- /dev/null +++ b/benchmarks/src/lib.rs @@ -0,0 +1,55 @@ +use rouille::{Request, Response}; +use std::net::SocketAddr; +use std::thread; +use std::sync::Arc; + +pub struct TestServer { + addr: SocketAddr, + counter: Option>, + handle: Option>, +} + +impl TestServer { + pub fn static_response(body: &'static [u8]) -> Self { + Self::new(move |_| { + use std::io::Cursor; + + rouille::Response { + status_code: 200, + headers: vec![], + data: rouille::ResponseBody::from_reader(Cursor::new(body)), + upgrade: None, + } + }) + } + + pub fn new(handler: impl Send + Sync + 'static + Fn(&Request) -> Response) -> Self { + let server = rouille::Server::new("localhost:0", handler).unwrap(); + let addr = server.server_addr(); + + let counter_outer = Arc::new(()); + let counter_inner = counter_outer.clone(); + let handle = thread::spawn(move || { + while Arc::strong_count(&counter_inner) > 1 { + server.poll(); + } + }); + + Self { + addr: addr, + counter: Some(counter_outer), + handle: Some(handle), + } + } + + pub fn endpoint(&self) -> String { + format!("http://{}", self.addr) + } +} + +impl Drop for TestServer { + fn drop(&mut self) { + self.counter.take(); + self.handle.take().unwrap().join().unwrap(); + } +} diff --git a/src/agent.rs b/src/agent.rs index 98ede78b..0ad5afb0 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -11,6 +11,7 @@ use crate::handler::RequestHandler; use crate::task::{UdpWaker, WakerExt}; use crate::Error; use crossbeam_channel::{Receiver, Sender}; +use crossbeam_utils::sync::WaitGroup; use curl::multi::WaitFd; use futures_util::task::ArcWake; use slab::Slab; @@ -107,7 +108,10 @@ pub(crate) fn new() -> Result { let (message_tx, message_rx) = crossbeam_channel::unbounded(); - Ok(Handle { + let wait_group = WaitGroup::new(); + let wait_group_thread = wait_group.clone(); + + let handle = Handle { message_tx: message_tx.clone(), waker: waker.clone(), join_handle: Some( @@ -125,12 +129,17 @@ pub(crate) fn new() -> Result { waker, }; + drop(wait_group_thread); log::debug!("agent took {:?} to start up", create_start.elapsed()); agent.run() })?, ), - }) + }; + + wait_group.wait(); + + Ok(handle) } impl Handle {