Skip to content

Commit

Permalink
chore: add benchmarks for no-op submission (#144)
Browse files Browse the repository at this point in the history
Co-authored-by: ollie-etl <Oliver Bunting@etlsystems.com>
  • Loading branch information
ollie-etl and ollie-etl authored Oct 24, 2022
1 parent 13f7409 commit c6b884e
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 1 deletion.
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ jobs:
steps:
- run: exit 0

bench:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
run: rustup update stable
- run: cargo bench --no-run

check:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -59,7 +67,6 @@ jobs:
run: rustup update stable
- run: cargo test --doc


fmt:
runs-on: ubuntu-latest
steps:
Expand Down
13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ bytes = { version = "1.0", optional = true }
[dev-dependencies]
tempfile = "3.2.0"
tokio-test = "0.4.2"
iai = "0.1.1"
futures = "0.3.25"
criterion = "0.4.0"

[package.metadata.docs.rs]
all-features = true

[[bench]]
name = "lai_no_op"
path = "benches/lai/no_op.rs"
harness = false

[[bench]]
name = "criterion_no_op"
path = "benches/criterion/no_op.rs"
harness = false
79 changes: 79 additions & 0 deletions benches/criterion/no_op.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use criterion::{
criterion_group, criterion_main, BenchmarkId, Criterion, SamplingMode, Throughput,
};
use std::time::{Duration, Instant};

use futures::stream::{self, StreamExt};

#[derive(Clone)]
struct Options {
iterations: usize,
concurrency: usize,
sq_size: usize,
cq_size: usize,
}

impl Default for Options {
fn default() -> Self {
Self {
iterations: 100000,
concurrency: 1,
sq_size: 128,
cq_size: 256,
}
}
}

fn run_no_ops(opts: &Options, count: u64) -> Duration {
let mut ring_opts = tokio_uring::uring_builder();
ring_opts
.setup_cqsize(opts.cq_size as _)
// .setup_sqpoll(10)
// .setup_sqpoll_cpu(1)
;

let mut m = Duration::ZERO;

// Run the required number of iterations
for _ in 0..count {
m += tokio_uring::builder()
.entries(opts.sq_size as _)
.uring_builder(&ring_opts)
.start(async move {
let start = Instant::now();
stream::iter(0..opts.iterations)
.for_each_concurrent(Some(opts.concurrency), |_| async move {
tokio_uring::no_op().await.unwrap();
})
.await;
start.elapsed()
})
}
m
}

fn bench(c: &mut Criterion) {
let mut group = c.benchmark_group("no_op");
let mut opts = Options::default();
for concurrency in [1, 32, 64, 256].iter() {
opts.concurrency = *concurrency;

// We perform long running benchmarks: this is the best mode
group.sampling_mode(SamplingMode::Flat);

group.throughput(Throughput::Elements(opts.iterations as u64));
group.bench_with_input(
BenchmarkId::from_parameter(concurrency),
&opts,
|b, opts| {
// Custom iterator used because we don't expose access to runtime,
// which is required to do async benchmarking with criterion
b.iter_custom(move |iter| run_no_ops(opts, iter));
},
);
}
group.finish();
}

criterion_group!(benches, bench);
criterion_main!(benches);
83 changes: 83 additions & 0 deletions benches/lai/no_op.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use futures::stream::{self, StreamExt};
use iai::black_box;

#[derive(Clone)]
struct Options {
iterations: usize,
concurrency: usize,
sq_size: usize,
cq_size: usize,
}

impl Default for Options {
fn default() -> Self {
Self {
iterations: 100000,
concurrency: 1,
sq_size: 64,
cq_size: 256,
}
}
}

fn runtime_only() -> Result<(), Box<dyn std::error::Error>> {
let opts = Options::default();
let mut ring_opts = tokio_uring::uring_builder();
ring_opts
.setup_cqsize(opts.cq_size as _)
// .setup_sqpoll(10)
// .setup_sqpoll_cpu(1)
;

tokio_uring::builder()
.entries(opts.sq_size as _)
.uring_builder(&ring_opts)
.start(async move { black_box(Ok(())) })
}

fn run_no_ops(opts: Options) -> Result<(), Box<dyn std::error::Error>> {
let mut ring_opts = tokio_uring::uring_builder();
ring_opts
.setup_cqsize(opts.cq_size as _)
// .setup_sqpoll(10)
// .setup_sqpoll_cpu(1)
;

tokio_uring::builder()
.entries(opts.sq_size as _)
.uring_builder(&ring_opts)
.start(async move {
stream::iter(0..opts.iterations)
.for_each_concurrent(Some(opts.concurrency), |_| async move {
tokio_uring::no_op().await.unwrap();
})
.await;
Ok(())
})
}

// This provides a baseline for estimating op overhead on top of this
fn no_op_x1() -> Result<(), Box<dyn std::error::Error>> {
let opts = Options::default();
run_no_ops(black_box(opts))
}

fn no_op_x32() -> Result<(), Box<dyn std::error::Error>> {
let mut opts = Options::default();
opts.concurrency = 32;
run_no_ops(black_box(opts))
}

fn no_op_x64() -> Result<(), Box<dyn std::error::Error>> {
let mut opts = Options::default();
opts.concurrency = 64;
run_no_ops(black_box(opts))
}

fn no_op_x256() -> Result<(), Box<dyn std::error::Error>> {
let mut opts = Options::default();
opts.concurrency = 256;
run_no_ops(black_box(opts))
}

iai::main!(runtime_only, no_op_x1, no_op_x32, no_op_x64, no_op_x256);

0 comments on commit c6b884e

Please sign in to comment.