From 10fcb047c6a6500889a2af5722adc9a5d36d9a8d Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sat, 4 Apr 2020 09:36:33 -0700 Subject: [PATCH] Add a spawn_blocking version of spin. --- README.md | 107 +++++++++++++++++++++++++++++++++++++------------ run_benches.sh | 11 +++++ src/main.rs | 51 +++++++++++++++++++---- 3 files changed, 136 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 4210c18..bc4d079 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,64 @@ # CPU Info -## Logical CPUs 8 -## Physical CPUs 4 + * Logical CPUs 8 + * Physical CPUs 4 # Benchmark results +## Spin w/ spin_spawn_blocking: +### `wrk -t 16 -d 5 --timeout 5 -c 16 http://localhost:3030/spin_spawn_blocking/1` + +``` +Running 5s test @ http://localhost:3030/spin_spawn_blocking/1 + 16 threads and 16 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 1.01s 6.67ms 1.03s 86.57% + Req/Sec 0.16 0.37 1.00 83.58% + 67 requests in 5.09s, 9.95KB read +Requests/sec: 13.15 +Transfer/sec: 1.95KB +``` + +## Spin w/ spin_spawn_blocking: +### `wrk -t 16 -d 5 --timeout 5 -c 32 http://localhost:3030/spin_spawn_blocking/1` + +``` +Running 5s test @ http://localhost:3030/spin_spawn_blocking/1 + 16 threads and 32 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 1.01s 10.23ms 1.05s 79.10% + Req/Sec 1.77 2.50 10.00 91.89% + 134 requests in 5.08s, 19.79KB read +Requests/sec: 26.37 +Transfer/sec: 3.89KB +``` + +## Spin w/ spin_spawn_blocking: +### `wrk -t 16 -d 5 --timeout 5 -c 64 http://localhost:3030/spin_spawn_blocking/1` + +``` +Running 5s test @ http://localhost:3030/spin_spawn_blocking/1 + 16 threads and 64 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 1.02s 18.05ms 1.09s 69.92% + Req/Sec 6.47 7.76 30.00 88.24% + 256 requests in 5.10s, 37.75KB read +Requests/sec: 50.23 +Transfer/sec: 7.41KB +``` + +## Spin w/ spin_spawn_blocking: +### `wrk -t 16 -d 5 --timeout 5 -c 128 http://localhost:3030/spin_spawn_blocking/1` + +``` +Running 5s test @ http://localhost:3030/spin_spawn_blocking/1 + 16 threads and 128 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 1.06s 45.69ms 1.26s 73.05% + Req/Sec 17.77 16.77 70.00 83.52% + 512 requests in 5.09s, 75.50KB read +Requests/sec: 100.57 +Transfer/sec: 14.83KB +``` + ## Sleep: ### `wrk -t 16 -d 5 --timeout 5 -c 16 http://localhost:3030/sleep/1` @@ -10,11 +66,11 @@ Running 5s test @ http://localhost:3030/sleep/1 16 threads and 16 connections Thread Stats Avg Stdev Max +/- Stdev - Latency 1.00s 529.36us 1.00s 70.31% - Req/Sec 0.28 0.45 1.00 71.88% - 64 requests in 5.01s, 8.50KB read -Requests/sec: 12.78 -Transfer/sec: 1.70KB + Latency 1.00s 620.32us 1.00s 61.76% + Req/Sec 0.41 0.50 1.00 58.82% + 68 requests in 5.08s, 9.03KB read +Requests/sec: 13.38 +Transfer/sec: 1.78KB ``` ## Sleep: @@ -24,11 +80,11 @@ Transfer/sec: 1.70KB Running 5s test @ http://localhost:3030/sleep/1 16 threads and 32 connections Thread Stats Avg Stdev Max +/- Stdev - Latency 1.00s 519.15us 1.00s 64.03% - Req/Sec 3.48 3.96 10.00 73.47% - 139 requests in 5.10s, 18.46KB read -Requests/sec: 27.26 -Transfer/sec: 3.62KB + Latency 1.00s 387.66us 1.00s 60.16% + Req/Sec 1.58 1.58 10.00 96.97% + 128 requests in 5.01s, 17.00KB read +Requests/sec: 25.57 +Transfer/sec: 3.40KB ``` ## Sleep: @@ -38,11 +94,11 @@ Transfer/sec: 3.62KB Running 5s test @ http://localhost:3030/sleep/1 16 threads and 64 connections Thread Stats Avg Stdev Max +/- Stdev - Latency 1.00s 0.85ms 1.00s 65.23% - Req/Sec 5.75 8.14 30.00 90.14% - 256 requests in 5.01s, 34.00KB read -Requests/sec: 51.14 -Transfer/sec: 6.79KB + Latency 1.00s 723.94us 1.00s 77.65% + Req/Sec 4.35 5.56 30.00 95.65% + 264 requests in 5.01s, 35.06KB read +Requests/sec: 52.65 +Transfer/sec: 6.99KB ``` ## Sleep: @@ -52,10 +108,10 @@ Transfer/sec: 6.79KB Running 5s test @ http://localhost:3030/sleep/1 16 threads and 128 connections Thread Stats Avg Stdev Max +/- Stdev - Latency 1.00s 708.55us 1.00s 68.55% - Req/Sec 13.17 19.52 70.00 88.89% + Latency 1.00s 2.19ms 1.01s 83.59% + Req/Sec 10.49 15.08 70.00 94.12% 512 requests in 5.01s, 68.00KB read -Requests/sec: 102.26 +Requests/sec: 102.22 Transfer/sec: 13.58KB ``` @@ -66,10 +122,11 @@ Transfer/sec: 13.58KB Running 5s test @ http://localhost:3030/spin/1 16 threads and 16 connections Thread Stats Avg Stdev Max +/- Stdev - Latency 2.70s 1.42s 5.00s 60.00% - Req/Sec 0.00 0.00 0.00 100.00% - 20 requests in 5.10s, 2.97KB read -Requests/sec: 3.92 -Transfer/sec: 596.05B + Latency 2.53s 1.61s 5.00s 84.21% + Req/Sec 0.15 0.37 1.00 85.00% + 20 requests in 5.02s, 2.97KB read + Socket errors: connect 0, read 0, write 0, timeout 1 +Requests/sec: 3.98 +Transfer/sec: 605.59B ``` diff --git a/run_benches.sh b/run_benches.sh index 8924c9d..a9c1feb 100755 --- a/run_benches.sh +++ b/run_benches.sh @@ -21,6 +21,17 @@ echo "PID ${PID:?}" }> README.md echo "# Benchmark results" >> README.md +for CONNECTIONS in 16 32 64 128; do +SPIN_BLOCKING_CMD="${WRK:?} -c ${CONNECTIONS} http://localhost:3030/spin_spawn_blocking/1" +{ +echo "## Spin w/ spin_spawn_blocking:" +echo "### \`${SPIN_BLOCKING_CMD:?}\`" +echo "" +block_quote ${SPIN_BLOCKING_CMD:?} +echo "" +} >> README.md +done + for CONNECTIONS in 16 32 64 128; do SLEEP_CMD="${WRK:?} -c ${CONNECTIONS} http://localhost:3030/sleep/1" { diff --git a/src/main.rs b/src/main.rs index 5ba16e1..26c8377 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,19 @@ use std::convert::Infallible; use std::time::{Duration, Instant}; +use tokio::task; use warp::Filter; +fn error_response(err: E) -> warp::reply::WithStatus +where + E: std::error::Error, +{ + warp::reply::with_status( + format!("{}", err), + warp::http::StatusCode::INTERNAL_SERVER_ERROR, + ) +} + #[tokio::main] async fn main() { // Setup logging @@ -20,13 +31,18 @@ async fn main() { .and_then(sleepy); // Match `/spin/:Seconds`... and burn CPU for N seconds... let spin = warp::path("spin").and(warp::path::param()).and_then(spin); - let info = warp::path("info").map(||{ - format!(r#"# CPU Info -## Logical CPUs {} -## Physical CPUs {} -"#, -num_cpus::get(), -num_cpus::get_physical()) + let spin_spawn_blocking = warp::path("spin_spawn_blocking") + .and(warp::path::param()) + .and_then(spin_spawn_blocking); + let info = warp::path("info").map(|| { + format!( + r#"# CPU Info + * Logical CPUs {} + * Physical CPUs {} +"#, + num_cpus::get(), + num_cpus::get_physical() + ) }); let index = warp::any().map(|| { warp::http::Response::builder() @@ -34,11 +50,12 @@ num_cpus::get_physical()) .body( r#"warp test
Spin for 5 seconds
+
Spin w/spawn_blocking for 5 seconds
Sleep for 5 seconds
"#, ) }); - let routes = info.or(sleepy).or(spin).or(index); + let routes = info.or(spin_spawn_blocking).or(sleepy).or(spin).or(index); let routes = routes.with(warp::log("warptest")); println!("Listening on :3030"); @@ -56,6 +73,24 @@ async fn spin(seconds: u64) -> Result { } } +async fn spin_spawn_blocking(seconds: u64) -> Result { + let res = task::spawn_blocking(move || { + let end = Instant::now() + Duration::new(seconds, 0); + let mut cnt = 0; + loop { + cnt += 1; + if Instant::now() > end { + return format!("I spun {} times in {} seconds!", cnt, seconds); + } + } + }) + .await; + Ok(match res { + Ok(r) => warp::reply::with_status(r, warp::http::StatusCode::OK), + Err(e) => error_response(e), + }) +} + async fn sleepy(seconds: u64) -> Result { tokio::time::delay_for(Duration::from_secs(seconds)).await; Ok(format!("I waited {} seconds!", seconds))