@@ -36,10 +36,15 @@ mod report;
3636mod routine;
3737mod stats;
3838
39+ use core:: future:: Future ;
40+ use core:: pin:: Pin ;
41+ use core:: ptr;
42+ use core:: task:: { Context , Poll , RawWaker , RawWakerVTable , Waker } ;
3943use core:: time:: Duration ;
4044use libm:: { ceil, sqrt} ;
4145use serde:: { Deserialize , Serialize } ;
4246
47+ use alloc:: boxed:: Box ;
4348use alloc:: vec;
4449use alloc:: vec:: Vec ;
4550use benchmark:: BenchmarkConfig ;
@@ -249,6 +254,7 @@ impl<M: Measurement> Criterion<M> {
249254 self
250255 }
251256}
257+
252258impl < M > Criterion < M >
253259where
254260 M : Measurement + ' static ,
@@ -264,7 +270,7 @@ where
264270 /// fn bench(c: &mut Criterion) {
265271 /// // Setup (construct data, allocate memory, etc)
266272 /// c.bench_function(
267- /// "function_name ",
273+ /// "bench desc ",
268274 /// |b| b.iter(|| {
269275 /// // Code to benchmark goes here
270276 /// }),
@@ -274,9 +280,69 @@ where
274280 pub fn bench_function < F > ( & mut self , desc : & str , f : F ) -> & mut Criterion < M >
275281 where
276282 F : FnMut ( & mut Bencher < ' _ , M > ) ,
283+ {
284+ const NOOP : RawWaker = {
285+ const VTABLE : RawWakerVTable = RawWakerVTable :: new (
286+ // Cloning just returns a new no-op raw waker
287+ |_| NOOP ,
288+ // `wake` does nothing
289+ |_| { } ,
290+ // `wake_by_ref` does nothing
291+ |_| { } ,
292+ // Dropping does nothing as we don't allocate anything
293+ |_| { } ,
294+ ) ;
295+ RawWaker :: new ( ptr:: null ( ) , & VTABLE )
296+ } ;
297+
298+ // bench_function never be pending
299+ fn block_on ( f : impl Future < Output = ( ) > ) {
300+ let waker = unsafe { Waker :: from_raw ( NOOP ) } ;
301+ let mut ctx = Context :: from_waker ( & waker) ;
302+ match core:: pin:: pin!( f) . poll ( & mut ctx) {
303+ Poll :: Ready ( _) => ( ) ,
304+ // sync functions not be pending
305+ Poll :: Pending => unreachable ! ( ) ,
306+ }
307+ }
308+
309+ let id = report:: BenchmarkId :: new ( desc. into ( ) ) ;
310+ block_on ( analysis:: common (
311+ & id,
312+ & mut routine:: Function :: new ( f) ,
313+ & self . config ,
314+ self ,
315+ ) ) ;
316+
317+ self
318+ }
319+
320+ /// Benchmarks a future.
321+ ///
322+ /// # Example
323+ ///
324+ /// ```rust
325+ /// use wasm_bindgen_test::{Criterion, wasm_bindgen_bench};
326+ ///
327+ /// #[wasm_bindgen_bench]
328+ /// async fn bench(c: &mut Criterion) {
329+ /// // Setup (construct data, allocate memory, etc)
330+ /// c.bench_async_function(
331+ /// "bench desc",
332+ /// Box::pin(
333+ /// b.iter_future(|| async {
334+ /// // Code to benchmark goes here
335+ /// })
336+ /// )
337+ /// ).await;
338+ /// }
339+ /// ```
340+ pub async fn bench_async_function < F > ( & mut self , desc : & str , f : F ) -> & mut Criterion < M >
341+ where
342+ for < ' b > F : FnMut ( & ' b mut Bencher < ' _ , M > ) -> Pin < Box < dyn Future < Output = ( ) > + ' b > > ,
277343 {
278344 let id = report:: BenchmarkId :: new ( desc. into ( ) ) ;
279- analysis:: common ( & id, & mut routine:: Function :: new ( f) , & self . config , self ) ;
345+ analysis:: common ( & id, & mut routine:: AsyncFunction :: new ( f) , & self . config , self ) . await ;
280346 self
281347 }
282348}
0 commit comments