1818
1919 from pytest import Session
2020
21+ from pytest_codspeed .config import PedanticOptions
2122 from pytest_codspeed .instruments import P , T
2223 from pytest_codspeed .plugin import BenchmarkMarkerOptions , CodSpeedConfig
2324
@@ -149,66 +150,6 @@ class Benchmark:
149150 stats : BenchmarkStats
150151
151152
152- def run_benchmark (
153- name : str , uri : str , fn : Callable [P , T ], args , kwargs , config : BenchmarkConfig
154- ) -> tuple [Benchmark , T ]:
155- # Compute the actual result of the function
156- out = fn (* args , ** kwargs )
157-
158- # Warmup
159- times_per_round_ns : list [float ] = []
160- warmup_start = start = perf_counter_ns ()
161- while True :
162- start = perf_counter_ns ()
163- fn (* args , ** kwargs )
164- end = perf_counter_ns ()
165- times_per_round_ns .append (end - start )
166- if end - warmup_start > config .warmup_time_ns :
167- break
168-
169- # Round sizing
170- warmup_mean_ns = mean (times_per_round_ns )
171- warmup_iters = len (times_per_round_ns )
172- times_per_round_ns .clear ()
173- iter_per_round = (
174- int (ceil (config .min_round_time_ns / warmup_mean_ns ))
175- if warmup_mean_ns <= config .min_round_time_ns
176- else 1
177- )
178- if config .max_rounds is None :
179- round_time_ns = warmup_mean_ns * iter_per_round
180- rounds = int (config .max_time_ns / round_time_ns )
181- else :
182- rounds = config .max_rounds
183- rounds = max (1 , rounds )
184-
185- # Benchmark
186- iter_range = range (iter_per_round )
187- run_start = perf_counter_ns ()
188- for _ in range (rounds ):
189- start = perf_counter_ns ()
190- for _ in iter_range :
191- fn (* args , ** kwargs )
192- end = perf_counter_ns ()
193- times_per_round_ns .append (end - start )
194-
195- if end - run_start > config .max_time_ns :
196- # TODO: log something
197- break
198- benchmark_end = perf_counter_ns ()
199- total_time = (benchmark_end - run_start ) / 1e9
200-
201- stats = BenchmarkStats .from_list (
202- times_per_round_ns ,
203- rounds = rounds ,
204- total_time = total_time ,
205- iter_per_round = iter_per_round ,
206- warmup_iters = warmup_iters ,
207- )
208-
209- return Benchmark (name = name , uri = uri , config = config , stats = stats ), out
210-
211-
212153class WallTimeInstrument (Instrument ):
213154 instrument = "walltime"
214155
@@ -228,21 +169,126 @@ def measure(
228169 * args : P .args ,
229170 ** kwargs : P .kwargs ,
230171 ) -> T :
231- bench , out = run_benchmark (
232- name = name ,
233- uri = uri ,
234- fn = fn ,
235- args = args ,
236- kwargs = kwargs ,
237- config = BenchmarkConfig .from_codspeed_config_and_marker_data (
238- self .config , marker_options
239- ),
172+ benchmark_config = BenchmarkConfig .from_codspeed_config_and_marker_data (
173+ self .config , marker_options
174+ )
175+
176+ # Compute the actual result of the function
177+ out = fn (* args , ** kwargs )
178+ # Warmup
179+ times_per_round_ns : list [float ] = []
180+ warmup_start = start = perf_counter_ns ()
181+ while True :
182+ start = perf_counter_ns ()
183+ fn (* args , ** kwargs )
184+ end = perf_counter_ns ()
185+ times_per_round_ns .append (end - start )
186+ if end - warmup_start > benchmark_config .warmup_time_ns :
187+ break
188+
189+ # Round sizing
190+ warmup_mean_ns = mean (times_per_round_ns )
191+ warmup_iters = len (times_per_round_ns )
192+ times_per_round_ns .clear ()
193+ iter_per_round = (
194+ int (ceil (benchmark_config .min_round_time_ns / warmup_mean_ns ))
195+ if warmup_mean_ns <= benchmark_config .min_round_time_ns
196+ else 1
197+ )
198+ if benchmark_config .max_rounds is None :
199+ round_time_ns = warmup_mean_ns * iter_per_round
200+ rounds = int (benchmark_config .max_time_ns / round_time_ns )
201+ else :
202+ rounds = benchmark_config .max_rounds
203+ rounds = max (1 , rounds )
204+
205+ # Benchmark
206+ iter_range = range (iter_per_round )
207+ run_start = perf_counter_ns ()
208+ for _ in range (rounds ):
209+ start = perf_counter_ns ()
210+ for _ in iter_range :
211+ fn (* args , ** kwargs )
212+ end = perf_counter_ns ()
213+ times_per_round_ns .append (end - start )
214+
215+ if end - run_start > benchmark_config .max_time_ns :
216+ # TODO: log something
217+ break
218+ benchmark_end = perf_counter_ns ()
219+ total_time = (benchmark_end - run_start ) / 1e9
220+
221+ stats = BenchmarkStats .from_list (
222+ times_per_round_ns ,
223+ rounds = rounds ,
224+ total_time = total_time ,
225+ iter_per_round = iter_per_round ,
226+ warmup_iters = warmup_iters ,
227+ )
228+
229+ self .benchmarks .append (
230+ Benchmark (name = name , uri = uri , config = benchmark_config , stats = stats )
231+ )
232+ return out
233+
234+ def measure_pedantic (
235+ self ,
236+ marker_options : BenchmarkMarkerOptions ,
237+ pedantic_options : PedanticOptions [P , T ],
238+ name : str ,
239+ uri : str ,
240+ ) -> T :
241+ benchmark_config = BenchmarkConfig .from_codspeed_config_and_marker_data (
242+ self .config , marker_options
243+ )
244+
245+ iter_range = range (pedantic_options .iterations )
246+
247+ # Warmup
248+ for _ in range (pedantic_options .warmup_rounds ):
249+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
250+ for _ in iter_range :
251+ pedantic_options .target (* args , ** kwargs )
252+ if pedantic_options .teardown is not None :
253+ pedantic_options .teardown (* args , ** kwargs )
254+
255+ # Benchmark
256+ times_per_round_ns : list [float ] = []
257+ benchmark_start = perf_counter_ns ()
258+ for _ in range (pedantic_options .rounds ):
259+ start = perf_counter_ns ()
260+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
261+ for _ in iter_range :
262+ pedantic_options .target (* args , ** kwargs )
263+ end = perf_counter_ns ()
264+ times_per_round_ns .append (end - start )
265+ if pedantic_options .teardown is not None :
266+ pedantic_options .teardown (* args , ** kwargs )
267+
268+ benchmark_end = perf_counter_ns ()
269+ total_time = (benchmark_end - benchmark_start ) / 1e9
270+ stats = BenchmarkStats .from_list (
271+ times_per_round_ns ,
272+ rounds = pedantic_options .rounds ,
273+ total_time = total_time ,
274+ iter_per_round = pedantic_options .iterations ,
275+ warmup_iters = pedantic_options .warmup_rounds ,
276+ )
277+
278+ # Compute the actual result of the function
279+ args , kwargs = pedantic_options .setup_and_get_args_kwargs ()
280+ out = pedantic_options .target (* args , ** kwargs )
281+ if pedantic_options .teardown is not None :
282+ pedantic_options .teardown (* args , ** kwargs )
283+
284+ self .benchmarks .append (
285+ Benchmark (name = name , uri = uri , config = benchmark_config , stats = stats )
240286 )
241- self .benchmarks .append (bench )
242287 return out
243288
244289 def report (self , session : Session ) -> None :
245290 reporter = session .config .pluginmanager .get_plugin ("terminalreporter" )
291+ assert reporter is not None , "terminalreporter not found"
246292
247293 if len (self .benchmarks ) == 0 :
248294 reporter .write_sep (
0 commit comments