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 //! * Async-std
7 //! * Smol
8 //! * The Futures crate
9 //!
10 //! Please note that async benchmarks will have a small amount of measurement overhead relative
11 //! to synchronous benchmarks. It is recommended to use synchronous benchmarks where possible, to
12 //! improve measurement accuracy.
13 
14 use std::future::Future;
15 
16 /// Plugin trait used to allow benchmarking on multiple different async runtimes.
17 ///
18 /// Smol, Tokio and Async-std are supported out of the box, as is the current-thread runner from the
19 /// Futures crate; it is recommended to use whichever runtime you use in production.
20 pub trait AsyncExecutor {
21     /// Spawn the given future onto this runtime and block until it's complete, returning the result.
block_on<T>(&self, future: impl Future<Output = T>) -> T22     fn block_on<T>(&self, future: impl Future<Output = T>) -> T;
23 }
24 
25 /// Runs futures on the 'futures' crate's built-in current-thread executor
26 #[cfg(feature = "async_futures")]
27 pub struct FuturesExecutor;
28 #[cfg(feature = "async_futures")]
29 impl AsyncExecutor for FuturesExecutor {
block_on<T>(&self, future: impl Future<Output = T>) -> T30     fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
31         futures::executor::block_on(future)
32     }
33 }
34 
35 /// Runs futures on the 'soml' crate's global executor
36 #[cfg(feature = "async_smol")]
37 pub struct SmolExecutor;
38 #[cfg(feature = "async_smol")]
39 impl AsyncExecutor for SmolExecutor {
block_on<T>(&self, future: impl Future<Output = T>) -> T40     fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
41         smol::block_on(future)
42     }
43 }
44 
45 #[cfg(feature = "async_tokio")]
46 impl AsyncExecutor for tokio::runtime::Runtime {
block_on<T>(&self, future: impl Future<Output = T>) -> T47     fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
48         self.block_on(future)
49     }
50 }
51 #[cfg(feature = "async_tokio")]
52 impl AsyncExecutor for &tokio::runtime::Runtime {
block_on<T>(&self, future: impl Future<Output = T>) -> T53     fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
54         (*self).block_on(future)
55     }
56 }
57 
58 /// Runs futures on the 'async-std' crate's global executor
59 #[cfg(feature = "async_std")]
60 pub struct AsyncStdExecutor;
61 #[cfg(feature = "async_std")]
62 impl AsyncExecutor for AsyncStdExecutor {
block_on<T>(&self, future: impl Future<Output = T>) -> T63     fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
64         async_std::task::block_on(future)
65     }
66 }
67