Add a spawn_blocking version of spin.

This commit is contained in:
Bill Thiede 2020-04-04 09:36:33 -07:00
parent 6abd91837f
commit 10fcb047c6
3 changed files with 136 additions and 33 deletions

107
README.md
View File

@ -1,8 +1,64 @@
# CPU Info # CPU Info
## Logical CPUs 8 * Logical CPUs 8
## Physical CPUs 4 * Physical CPUs 4
# Benchmark results # 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: ## Sleep:
### `wrk -t 16 -d 5 --timeout 5 -c 16 http://localhost:3030/sleep/1` ### `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 Running 5s test @ http://localhost:3030/sleep/1
16 threads and 16 connections 16 threads and 16 connections
Thread Stats Avg Stdev Max +/- Stdev Thread Stats Avg Stdev Max +/- Stdev
Latency 1.00s 529.36us 1.00s 70.31% Latency 1.00s 620.32us 1.00s 61.76%
Req/Sec 0.28 0.45 1.00 71.88% Req/Sec 0.41 0.50 1.00 58.82%
64 requests in 5.01s, 8.50KB read 68 requests in 5.08s, 9.03KB read
Requests/sec: 12.78 Requests/sec: 13.38
Transfer/sec: 1.70KB Transfer/sec: 1.78KB
``` ```
## Sleep: ## Sleep:
@ -24,11 +80,11 @@ Transfer/sec: 1.70KB
Running 5s test @ http://localhost:3030/sleep/1 Running 5s test @ http://localhost:3030/sleep/1
16 threads and 32 connections 16 threads and 32 connections
Thread Stats Avg Stdev Max +/- Stdev Thread Stats Avg Stdev Max +/- Stdev
Latency 1.00s 519.15us 1.00s 64.03% Latency 1.00s 387.66us 1.00s 60.16%
Req/Sec 3.48 3.96 10.00 73.47% Req/Sec 1.58 1.58 10.00 96.97%
139 requests in 5.10s, 18.46KB read 128 requests in 5.01s, 17.00KB read
Requests/sec: 27.26 Requests/sec: 25.57
Transfer/sec: 3.62KB Transfer/sec: 3.40KB
``` ```
## Sleep: ## Sleep:
@ -38,11 +94,11 @@ Transfer/sec: 3.62KB
Running 5s test @ http://localhost:3030/sleep/1 Running 5s test @ http://localhost:3030/sleep/1
16 threads and 64 connections 16 threads and 64 connections
Thread Stats Avg Stdev Max +/- Stdev Thread Stats Avg Stdev Max +/- Stdev
Latency 1.00s 0.85ms 1.00s 65.23% Latency 1.00s 723.94us 1.00s 77.65%
Req/Sec 5.75 8.14 30.00 90.14% Req/Sec 4.35 5.56 30.00 95.65%
256 requests in 5.01s, 34.00KB read 264 requests in 5.01s, 35.06KB read
Requests/sec: 51.14 Requests/sec: 52.65
Transfer/sec: 6.79KB Transfer/sec: 6.99KB
``` ```
## Sleep: ## Sleep:
@ -52,10 +108,10 @@ Transfer/sec: 6.79KB
Running 5s test @ http://localhost:3030/sleep/1 Running 5s test @ http://localhost:3030/sleep/1
16 threads and 128 connections 16 threads and 128 connections
Thread Stats Avg Stdev Max +/- Stdev Thread Stats Avg Stdev Max +/- Stdev
Latency 1.00s 708.55us 1.00s 68.55% Latency 1.00s 2.19ms 1.01s 83.59%
Req/Sec 13.17 19.52 70.00 88.89% Req/Sec 10.49 15.08 70.00 94.12%
512 requests in 5.01s, 68.00KB read 512 requests in 5.01s, 68.00KB read
Requests/sec: 102.26 Requests/sec: 102.22
Transfer/sec: 13.58KB Transfer/sec: 13.58KB
``` ```
@ -66,10 +122,11 @@ Transfer/sec: 13.58KB
Running 5s test @ http://localhost:3030/spin/1 Running 5s test @ http://localhost:3030/spin/1
16 threads and 16 connections 16 threads and 16 connections
Thread Stats Avg Stdev Max +/- Stdev Thread Stats Avg Stdev Max +/- Stdev
Latency 2.70s 1.42s 5.00s 60.00% Latency 2.53s 1.61s 5.00s 84.21%
Req/Sec 0.00 0.00 0.00 100.00% Req/Sec 0.15 0.37 1.00 85.00%
20 requests in 5.10s, 2.97KB read 20 requests in 5.02s, 2.97KB read
Requests/sec: 3.92 Socket errors: connect 0, read 0, write 0, timeout 1
Transfer/sec: 596.05B Requests/sec: 3.98
Transfer/sec: 605.59B
``` ```

View File

@ -21,6 +21,17 @@ echo "PID ${PID:?}"
}> README.md }> README.md
echo "# Benchmark results" >> 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 for CONNECTIONS in 16 32 64 128; do
SLEEP_CMD="${WRK:?} -c ${CONNECTIONS} http://localhost:3030/sleep/1" SLEEP_CMD="${WRK:?} -c ${CONNECTIONS} http://localhost:3030/sleep/1"
{ {

View File

@ -3,8 +3,19 @@
use std::convert::Infallible; use std::convert::Infallible;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tokio::task;
use warp::Filter; use warp::Filter;
fn error_response<E>(err: E) -> warp::reply::WithStatus<String>
where
E: std::error::Error,
{
warp::reply::with_status(
format!("{}", err),
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
)
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
// Setup logging // Setup logging
@ -20,13 +31,18 @@ async fn main() {
.and_then(sleepy); .and_then(sleepy);
// Match `/spin/:Seconds`... and burn CPU for N seconds... // Match `/spin/:Seconds`... and burn CPU for N seconds...
let spin = warp::path("spin").and(warp::path::param()).and_then(spin); let spin = warp::path("spin").and(warp::path::param()).and_then(spin);
let info = warp::path("info").map(||{ let spin_spawn_blocking = warp::path("spin_spawn_blocking")
format!(r#"# CPU Info .and(warp::path::param())
## Logical CPUs {} .and_then(spin_spawn_blocking);
## Physical CPUs {} let info = warp::path("info").map(|| {
"#, format!(
num_cpus::get(), r#"# CPU Info
num_cpus::get_physical()) * Logical CPUs {}
* Physical CPUs {}
"#,
num_cpus::get(),
num_cpus::get_physical()
)
}); });
let index = warp::any().map(|| { let index = warp::any().map(|| {
warp::http::Response::builder() warp::http::Response::builder()
@ -34,11 +50,12 @@ num_cpus::get_physical())
.body( .body(
r#"<!DOCTYPE html><title>warp test</title><body> r#"<!DOCTYPE html><title>warp test</title><body>
<div><a href="/spin/5">Spin for 5 seconds</a></div> <div><a href="/spin/5">Spin for 5 seconds</a></div>
<div><a href="/spin_spawn_blocking/5">Spin w/spawn_blocking for 5 seconds</a></div>
<div><a href="/sleep/5">Sleep for 5 seconds</a></div> <div><a href="/sleep/5">Sleep for 5 seconds</a></div>
"#, "#,
) )
}); });
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")); let routes = routes.with(warp::log("warptest"));
println!("Listening on :3030"); println!("Listening on :3030");
@ -56,6 +73,24 @@ async fn spin(seconds: u64) -> Result<impl warp::Reply, Infallible> {
} }
} }
async fn spin_spawn_blocking(seconds: u64) -> Result<impl warp::Reply, Infallible> {
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<impl warp::Reply, Infallible> { async fn sleepy(seconds: u64) -> Result<impl warp::Reply, Infallible> {
tokio::time::delay_for(Duration::from_secs(seconds)).await; tokio::time::delay_for(Duration::from_secs(seconds)).await;
Ok(format!("I waited {} seconds!", seconds)) Ok(format!("I waited {} seconds!", seconds))