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