Skip to content

Commit be5bcc9

Browse files
committed
feat: add AsyncBencher support
1 parent 9c6a5a8 commit be5bcc9

File tree

6 files changed

+190
-2
lines changed

6 files changed

+190
-2
lines changed

crates/criterion_compat/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@ criterion = "0.4"
2020
codspeed = { path = "../codspeed", version = "1.0.0" }
2121
colored = "2.0.0"
2222

23+
futures = { version = "0.3", default_features = false, optional = true }
24+
smol = { version = "1.2", default-features = false, optional = true }
25+
tokio = { version = "1.0", default-features = false, features = [
26+
"rt",
27+
], optional = true }
28+
async-std = { version = "1.9", optional = true }
29+
30+
[features]
31+
async = ["futures", "criterion/async"]
32+
33+
async_futures = ["criterion/async_futures", "futures/executor", "async"]
34+
async_smol = ["criterion/async_smol", "smol", "async"]
35+
async_tokio = ["criterion/async_tokio", "tokio", "async"]
36+
async_std = ["criterion/async_std", "async-std", "async"]
37+
38+
2339
[[bench]]
2440
name = "criterion_example"
2541
harness = false

crates/criterion_compat/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,6 @@ Checked: benches/bencher_example.rs::fib_20 (group: benches)
7474
Finished running 1 benchmark suite(s)
7575
```
7676

77-
### Not supported yet:
77+
### Not supported:
7878

79-
- AsyncBencher
79+
- `iter_custom`
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use criterion::{async_executor::FuturesExecutor, criterion_group, BatchSize, Criterion};
2+
3+
fn some_benchmark(c: &mut Criterion) {
4+
let mut group = c.benchmark_group("async overhead");
5+
group.bench_function("iter", |b| b.to_async(FuturesExecutor).iter(|| async { 1 }));
6+
group.bench_function("iter_with_setup", |b| {
7+
b.to_async(FuturesExecutor)
8+
.iter_with_setup(|| (), |_| async { 1 })
9+
});
10+
group.bench_function("iter_with_large_setup", |b| {
11+
b.to_async(FuturesExecutor)
12+
.iter_with_large_setup(|| (), |_| async { 1 })
13+
});
14+
group.bench_function("iter_with_large_drop", |b| {
15+
b.to_async(FuturesExecutor)
16+
.iter_with_large_drop(|| async { 1 })
17+
});
18+
group.bench_function("iter_batched_small_input", |b| {
19+
b.to_async(FuturesExecutor)
20+
.iter_batched(|| (), |_| async { 1 }, BatchSize::SmallInput)
21+
});
22+
group.bench_function("iter_batched_large_input", |b| {
23+
b.to_async(FuturesExecutor)
24+
.iter_batched(|| (), |_| async { 1 }, BatchSize::LargeInput)
25+
});
26+
group.bench_function("iter_batched_per_iteration", |b| {
27+
b.to_async(FuturesExecutor)
28+
.iter_batched(|| (), |_| async { 1 }, BatchSize::PerIteration)
29+
});
30+
group.bench_function("iter_batched_ref_small_input", |b| {
31+
b.to_async(FuturesExecutor)
32+
.iter_batched_ref(|| (), |_| async { 1 }, BatchSize::SmallInput)
33+
});
34+
group.bench_function("iter_batched_ref_large_input", |b| {
35+
b.to_async(FuturesExecutor)
36+
.iter_batched_ref(|| (), |_| async { 1 }, BatchSize::LargeInput)
37+
});
38+
group.bench_function("iter_batched_ref_per_iteration", |b| {
39+
b.to_async(FuturesExecutor).iter_batched_ref(
40+
|| (),
41+
|_| async { 1 },
42+
BatchSize::PerIteration,
43+
)
44+
});
45+
group.finish();
46+
}
47+
48+
criterion_group!(benches, some_benchmark);

crates/criterion_compat/benches/criterion_integration/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,14 @@ pub mod measurement_overhead;
88
pub mod sampling_mode;
99
pub mod special_characters;
1010
pub mod with_inputs;
11+
12+
#[cfg(feature = "async_futures")]
13+
pub mod async_measurement_overhead;
14+
15+
#[cfg(not(feature = "async_futures"))]
16+
pub mod async_measurement_overhead {
17+
use criterion::{criterion_group, Criterion};
18+
fn some_benchmark(_c: &mut Criterion) {}
19+
20+
criterion_group!(benches, some_benchmark);
21+
}

crates/criterion_compat/benches/criterion_integration_main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ criterion_main! {
1313
criterion_integration::measurement_overhead::benches,
1414
criterion_integration::custom_measurement::benches,
1515
criterion_integration::sampling_mode::benches,
16+
criterion_integration::async_measurement_overhead::benches,
1617
}

crates/criterion_compat/src/compat/bencher.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ use codspeed::codspeed::{black_box, CodSpeed};
44
use colored::Colorize;
55
use criterion::BatchSize;
66

7+
#[cfg(feature = "async")]
8+
use criterion::async_executor::AsyncExecutor;
9+
#[cfg(feature = "async")]
10+
use std::future::Future;
11+
712
pub struct Bencher {
813
codspeed: Rc<RefCell<CodSpeed>>,
914
uri: String,
@@ -91,4 +96,111 @@ impl Bencher {
9196
drop(black_box(output));
9297
drop(black_box(input));
9398
}
99+
100+
#[cfg(feature = "async")]
101+
pub fn to_async<A: AsyncExecutor>(&mut self, runner: A) -> AsyncBencher<A, M> {
102+
AsyncBencher { b: self, runner }
103+
}
104+
}
105+
106+
pub struct AsyncBencher<A: AsyncExecutor> {
107+
b: &mut Bencher,
108+
runner: A,
109+
}
110+
111+
impl AsyncBencher {
112+
#[inline(never)]
113+
pub fn iter<O, R, F>(&mut self, mut routine: R)
114+
where
115+
R: FnMut() -> F,
116+
F: Future<Output = O>,
117+
{
118+
let AsyncBencher { b, runner } = self;
119+
runner.block_on(async {
120+
let mut codspeed = b.codspeed.borrow_mut();
121+
codspeed.start_benchmark(b.uri.as_str());
122+
black_box(routine().await);
123+
codspeed.end_benchmark();
124+
});
125+
}
126+
127+
#[inline(never)]
128+
pub fn iter_custom<R, F>(&mut self, mut routine: R)
129+
where
130+
R: FnMut(u64) -> F,
131+
F: Future<Output = M::Value>,
132+
{
133+
println!(
134+
"{} {} (CodSpeed doesn't support custom iterations)",
135+
"Skipping:".to_string().yellow(),
136+
self.uri.yellow(),
137+
);
138+
}
139+
140+
#[doc(hidden)]
141+
pub fn iter_with_setup<I, O, S, R, F>(&mut self, setup: S, routine: R)
142+
where
143+
S: FnMut() -> I,
144+
R: FnMut(I) -> F,
145+
F: Future<Output = O>,
146+
{
147+
self.iter_batched(setup, routine, BatchSize::PerIteration);
148+
}
149+
150+
pub fn iter_with_large_drop<O, R, F>(&mut self, mut routine: R)
151+
where
152+
R: FnMut() -> F,
153+
F: Future<Output = O>,
154+
{
155+
self.iter_batched(|| (), |_| routine(), BatchSize::SmallInput);
156+
}
157+
158+
#[doc(hidden)]
159+
pub fn iter_with_large_setup<I, O, S, R, F>(&mut self, setup: S, routine: R)
160+
where
161+
S: FnMut() -> I,
162+
R: FnMut(I) -> F,
163+
F: Future<Output = O>,
164+
{
165+
self.iter_batched(setup, routine, BatchSize::NumBatches(1));
166+
}
167+
168+
#[inline(never)]
169+
pub fn iter_batched<I, O, S, R, F>(&mut self, mut setup: S, mut routine: R, size: BatchSize)
170+
where
171+
S: FnMut() -> I,
172+
R: FnMut(I) -> F,
173+
F: Future<Output = O>,
174+
{
175+
let AsyncBencher { b, runner } = self;
176+
runner.block_on(async {
177+
let mut codspeed = b.codspeed.borrow_mut();
178+
let input = black_box(setup());
179+
codspeed.start_benchmark(b.uri.as_str());
180+
let output = routine(input);
181+
codspeed.end_benchmark();
182+
drop(black_box(output));
183+
})
184+
}
185+
186+
#[inline(never)]
187+
pub fn iter_batched_ref<I, O, S, R, F>(&mut self, mut setup: S, mut routine: R, size: BatchSize)
188+
where
189+
S: FnMut() -> I,
190+
R: FnMut(&mut I) -> F,
191+
F: Future<Output = O>,
192+
{
193+
let AsyncBencher { b, runner } = self;
194+
runner.block_on(async {
195+
let mut codspeed = b.codspeed.borrow_mut();
196+
let mut input = black_box(setup());
197+
198+
codspeed.start_benchmark(b.uri.as_str());
199+
let output = routine(&mut input);
200+
codspeed.end_benchmark();
201+
202+
drop(black_box(output));
203+
drop(black_box(input));
204+
});
205+
}
94206
}

0 commit comments

Comments
 (0)