criterion/
async_executor.rs

1//! This module defines a trait that can be used to plug in different Futures executors into
2//! Criterion.rs' async benchmarking support.
3//!
4//! Implementations are provided for:
5//! * Tokio (implemented directly for `tokio::Runtime`)
6//! * Smol
7//! * The Futures crate
8//!
9//! Please note that async benchmarks will have a small amount of measurement overhead relative
10//! to synchronous benchmarks. It is recommended to use synchronous benchmarks where possible, to
11//! improve measurement accuracy.
12
13use std::future::Future;
14
15/// Plugin trait used to allow benchmarking on multiple different async runtimes.
16///
17/// Smol and Tokio are supported out of the box, as is the current-thread runner from the
18/// Futures crate; it is recommended to use whichever runtime you use in production.
19pub trait AsyncExecutor {
20    /// Spawn the given future onto this runtime and block until it's complete, returning the result.
21    fn block_on<T>(&self, future: impl Future<Output = T>) -> T;
22}
23
24/// Runs futures on the 'futures' crate's built-in current-thread executor
25#[cfg(feature = "async_futures")]
26pub struct FuturesExecutor;
27#[cfg(feature = "async_futures")]
28impl AsyncExecutor for FuturesExecutor {
29    fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
30        futures::executor::block_on(future)
31    }
32}
33
34/// Runs futures on the 'smol' crate's global executor
35#[cfg(feature = "async_smol")]
36pub struct SmolExecutor;
37#[cfg(feature = "async_smol")]
38impl AsyncExecutor for SmolExecutor {
39    fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
40        smol::block_on(future)
41    }
42}
43
44#[cfg(feature = "async_tokio")]
45impl AsyncExecutor for tokio::runtime::Runtime {
46    fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
47        self.block_on(future)
48    }
49}
50#[cfg(feature = "async_tokio")]
51impl AsyncExecutor for &tokio::runtime::Runtime {
52    fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
53        (*self).block_on(future)
54    }
55}
56#[cfg(feature = "async_tokio")]
57impl AsyncExecutor for tokio::runtime::Handle {
58    fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
59        self.block_on(future)
60    }
61}
62#[cfg(feature = "async_tokio")]
63impl AsyncExecutor for &tokio::runtime::Handle {
64    fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
65        (*self).block_on(future)
66    }
67}