22
33import os
44import warnings
5+ from collections .abc import Awaitable
56from dataclasses import asdict , dataclass
67from math import ceil
78from statistics import mean , quantiles , stdev
@@ -182,31 +183,22 @@ def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]:
182183 )
183184 return config_str , []
184185
185- def measure (
186+ def _measure_iter (
186187 self ,
187188 marker_options : BenchmarkMarkerOptions ,
188189 name : str ,
189190 uri : str ,
190- fn : Callable [P , T ],
191- * args : P .args ,
192- ** kwargs : P .kwargs ,
193191 ) -> T :
194192 benchmark_config = BenchmarkConfig .from_codspeed_config_and_marker_data (
195193 self .config , marker_options
196194 )
197195
198- def __codspeed_root_frame__ () -> T :
199- return fn (* args , ** kwargs )
200-
201- # Compute the actual result of the function
202- out = __codspeed_root_frame__ ()
203-
204196 # Warmup
205197 times_per_round_ns : list [float ] = []
206198 warmup_start = start = perf_counter_ns ()
207199 while True :
208200 start = perf_counter_ns ()
209- __codspeed_root_frame__ ()
201+ yield
210202 end = perf_counter_ns ()
211203 times_per_round_ns .append (end - start )
212204 if end - warmup_start > benchmark_config .warmup_time_ns :
@@ -236,7 +228,7 @@ def __codspeed_root_frame__() -> T:
236228 for _ in range (rounds ):
237229 start = perf_counter_ns ()
238230 for _ in iter_range :
239- __codspeed_root_frame__ ()
231+ yield
240232 end = perf_counter_ns ()
241233 times_per_round_ns .append (end - start )
242234
@@ -260,9 +252,48 @@ def __codspeed_root_frame__() -> T:
260252 self .benchmarks .append (
261253 Benchmark (name = name , uri = uri , config = benchmark_config , stats = stats )
262254 )
255+
256+ def measure (
257+ self ,
258+ marker_options : BenchmarkMarkerOptions ,
259+ name : str ,
260+ uri : str ,
261+ fn : Callable [P , T ],
262+ * args : P .args ,
263+ ** kwargs : P .kwargs ,
264+ ) -> T :
265+ def __codspeed_root_frame__ () -> T :
266+ return fn (* args , ** kwargs )
267+
268+ # Compute the actual result of the function
269+ out = __codspeed_root_frame__ ()
270+
271+ for _ in self ._measure_iter (marker_options , name , uri ):
272+ __codspeed_root_frame__ ()
273+
274+ return out
275+
276+ async def measure_async (
277+ self ,
278+ marker_options : BenchmarkMarkerOptions ,
279+ name : str ,
280+ uri : str ,
281+ fn : Callable [P , Awaitable [T ]],
282+ * args : P .args ,
283+ ** kwargs : P .kwargs ,
284+ ) -> T :
285+ async def __codspeed_root_frame__ () -> T :
286+ return await fn (* args , ** kwargs )
287+
288+ # Compute the actual result of the function
289+ out = await __codspeed_root_frame__ ()
290+
291+ for _ in self ._measure_iter (marker_options , name , uri ):
292+ await __codspeed_root_frame__ ()
293+
263294 return out
264295
265- def measure_pedantic ( # noqa: C901
296+ def _measure_pedantic_iter ( # noqa: C901
266297 self ,
267298 marker_options : BenchmarkMarkerOptions ,
268299 pedantic_options : PedanticOptions [T ],
@@ -273,16 +304,12 @@ def measure_pedantic( # noqa: C901
273304 self .config , marker_options
274305 )
275306
276- def __codspeed_root_frame__ (* args , ** kwargs ) -> T :
277- return pedantic_options .target (* args , ** kwargs )
278-
279307 iter_range = range (pedantic_options .iterations )
280308
281309 # Warmup
282310 for _ in range (pedantic_options .warmup_rounds ):
283311 args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
284- for _ in iter_range :
285- __codspeed_root_frame__ (* args , ** kwargs )
312+ yield iter_range , args , kwargs
286313 if pedantic_options .teardown is not None :
287314 pedantic_options .teardown (* args , ** kwargs )
288315
@@ -294,8 +321,7 @@ def __codspeed_root_frame__(*args, **kwargs) -> T:
294321 for _ in range (pedantic_options .rounds ):
295322 start = perf_counter_ns ()
296323 args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
297- for _ in iter_range :
298- __codspeed_root_frame__ (* args , ** kwargs )
324+ yield iter_range , args , kwargs
299325 end = perf_counter_ns ()
300326 times_per_round_ns .append (end - start )
301327 if pedantic_options .teardown is not None :
@@ -313,15 +339,56 @@ def __codspeed_root_frame__(*args, **kwargs) -> T:
313339 warmup_iters = pedantic_options .warmup_rounds ,
314340 )
315341
342+ self .benchmarks .append (
343+ Benchmark (name = name , uri = uri , config = benchmark_config , stats = stats )
344+ )
345+
346+ def measure_pedantic (
347+ self ,
348+ marker_options : BenchmarkMarkerOptions ,
349+ pedantic_options : PedanticOptions [T ],
350+ name : str ,
351+ uri : str ,
352+ ) -> T :
353+ def __codspeed_root_frame__ (* args , ** kwargs ) -> T :
354+ return pedantic_options .target (* args , ** kwargs )
355+
356+ for i , args , kwargs in self ._measure_pedantic_iter (
357+ marker_options , pedantic_options , name , uri
358+ ):
359+ for _ in i :
360+ __codspeed_root_frame__ (* args , ** kwargs )
361+
316362 # Compute the actual result of the function
317363 args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
318364 out = __codspeed_root_frame__ (* args , ** kwargs )
319365 if pedantic_options .teardown is not None :
320366 pedantic_options .teardown (* args , ** kwargs )
321367
322- self .benchmarks .append (
323- Benchmark (name = name , uri = uri , config = benchmark_config , stats = stats )
324- )
368+ return out
369+
370+ async def measure_pedantic_async (
371+ self ,
372+ marker_options : BenchmarkMarkerOptions ,
373+ pedantic_options : PedanticOptions [T ],
374+ name : str ,
375+ uri : str ,
376+ ) -> T :
377+ async def __codspeed_root_frame__ (* args , ** kwargs ) -> T :
378+ return await pedantic_options .target (* args , ** kwargs )
379+
380+ for i , args , kwargs in self ._measure_pedantic_iter (
381+ marker_options , pedantic_options , name , uri
382+ ):
383+ for _ in i :
384+ await __codspeed_root_frame__ (* args , ** kwargs )
385+
386+ # Compute the actual result of the function
387+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
388+ out = await __codspeed_root_frame__ (* args , ** kwargs )
389+ if pedantic_options .teardown is not None :
390+ pedantic_options .teardown (* args , ** kwargs )
391+
325392 return out
326393
327394 def report (self , session : Session ) -> None :
0 commit comments