Skip to content

Commit 878b7a3

Browse files
committed
Introduced on_demand_benchmark decorator - see SciTools/iris#4621.
1 parent af1fd52 commit 878b7a3

File tree

3 files changed

+93
-22
lines changed

3 files changed

+93
-22
lines changed

benchmarks/benchmarks/__init__.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""Benchmark tests for iris-esmf-regrid"""
22

33

4+
from os import environ
5+
6+
47
def disable_repeat_between_setup(benchmark_object):
58
"""
69
Decorator for benchmarks where object persistence would be inappropriate.
@@ -30,15 +33,38 @@ def disable_repeat_between_setup(benchmark_object):
3033
def skip_benchmark(benchmark_object):
3134
"""
3235
Decorator for benchmarks skipping benchmarks.
36+
37+
Simply doesn't return the object.
38+
39+
Warnings
40+
--------
41+
ASV's architecture means decorated classes cannot be sub-classed. Code for
42+
inheritance should be in a mixin class that doesn't include any methods
43+
which ASV will recognise as benchmarks
44+
(e.g. ``def time_something(self):`` ).
45+
46+
"""
47+
pass
48+
49+
50+
def on_demand_benchmark(benchmark_object):
3351
"""
52+
Decorator. Disables these benchmark(s) unless ON_DEMAND_BENCHARKS env var is set.
3453
35-
def setup_cache(self):
36-
pass
54+
For benchmarks that, for whatever reason, should not be run by default.
55+
E.g:
56+
* Require a local file
57+
* Used for scalability analysis instead of commit monitoring.
3758
38-
def setup(*args):
39-
raise NotImplementedError
59+
Can be applied to benchmark classes/methods/functions.
4060
41-
benchmark_object.setup_cache = setup_cache
42-
benchmark_object.setup = setup
61+
Warnings
62+
--------
63+
ASV's architecture means decorated classes cannot be sub-classed. Code for
64+
inheritance should be in a mixin class that doesn't include any methods
65+
which ASV will recognise as benchmarks
66+
(e.g. ``def time_something(self):`` ).
4367
44-
return benchmark_object
68+
"""
69+
if "ON_DEMAND_BENCHMARKS" in environ:
70+
return benchmark_object

benchmarks/benchmarks/long/esmf_regridder.py

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
)
1616
from esmf_regrid.schemes import ESMFAreaWeightedRegridder
1717

18-
from .. import skip_benchmark
18+
from .. import on_demand_benchmark, skip_benchmark
1919
from ..generate_data import _grid_cube, _gridlike_mesh_cube
2020

2121

22-
class PrepareScalabilityGridToGrid:
22+
class PrepareScalabilityMixin:
2323
timeout = 180
2424
params = [50, 100, 200, 400, 600, 800]
2525
param_names = ["grid width"]
@@ -42,11 +42,18 @@ def setup(self, n):
4242
self.src = self.src_cube(n)
4343
self.tgt = self.tgt_cube(n)
4444

45-
def time_prepare(self, n):
45+
def _time_prepare(self, n):
4646
_ = self.regridder(self.src, self.tgt)
4747

4848

49-
class PrepareScalabilityMeshToGrid(PrepareScalabilityGridToGrid):
49+
@on_demand_benchmark
50+
class PrepareScalabilityGridToGrid(PrepareScalabilityMixin):
51+
def time_prepare(self, n):
52+
super()._time_prepare(n)
53+
54+
55+
@on_demand_benchmark
56+
class PrepareScalabilityMeshToGrid(PrepareScalabilityMixin):
5057
regridder = MeshToGridESMFRegridder
5158

5259
def src_cube(self, n):
@@ -83,10 +90,11 @@ def time_save(self, _, n):
8390
save_regridder(self.rg, self.destination_file)
8491

8592
def time_prepare(self, _, n):
86-
super().time_prepare(n)
93+
super()._time_prepare(n)
8794

8895

89-
class PrepareScalabilityGridToMesh(PrepareScalabilityGridToGrid):
96+
@on_demand_benchmark
97+
class PrepareScalabilityGridToMesh(PrepareScalabilityMixin):
9098
regridder = GridToMeshESMFRegridder
9199

92100
def tgt_cube(self, n):
@@ -123,10 +131,10 @@ def time_save(self, _, n):
123131
save_regridder(self.rg, self.destination_file)
124132

125133
def time_prepare(self, _, n):
126-
super().time_prepare(n)
134+
super()._time_prepare(n)
127135

128136

129-
class PerformScalabilityGridToGrid:
137+
class PerformScalabilityMixin:
130138
params = [100, 200, 400, 600, 800, 1000]
131139
param_names = ["height"]
132140
grid_size = 400
@@ -185,21 +193,31 @@ def setup(self, cache, height):
185193
cube = self.add_src_metadata(cube)
186194
self.result = regridder(cube)
187195

188-
def time_perform(self, cache, height):
196+
def _time_perform(self, cache, height):
189197
assert not self.src.has_lazy_data()
190198
rg, _ = cache
191199
_ = rg(self.src)
192200

193-
def time_lazy_perform(self, cache, height):
201+
def _time_lazy_perform(self, cache, height):
194202
# Don't touch result.data - permanent realisation plays badly with
195203
# ASV's re-run strategy.
196204
assert self.result.has_lazy_data()
197205
self.result.core_data().compute()
198206

199207

200-
class PerformScalabilityMeshToGrid(PerformScalabilityGridToGrid):
208+
@on_demand_benchmark
209+
class PerformScalabilityGridToGrid(PerformScalabilityMixin):
210+
def time_perform(self, cache, height):
211+
super()._time_perform(cache, height)
212+
213+
def time_lazy_perform(self, cache, height):
214+
super()._time_lazy_perform(cache, height)
215+
216+
217+
@on_demand_benchmark
218+
class PerformScalabilityMeshToGrid(PerformScalabilityMixin):
201219
regridder = MeshToGridESMFRegridder
202-
chunk_size = [PerformScalabilityGridToGrid.grid_size ^ 2, 10]
220+
chunk_size = [PerformScalabilityMixin.grid_size ^ 2, 10]
203221
file_name = "chunked_cube_1d.nc"
204222

205223
def setup_cache(self):
@@ -223,8 +241,15 @@ def add_src_metadata(self, cube):
223241
cube.add_aux_coord(mesh_coord_y, 0)
224242
return cube
225243

244+
def time_perform(self, cache, height):
245+
super()._time_perform(cache, height)
246+
247+
def time_lazy_perform(self, cache, height):
248+
super()._time_lazy_perform(cache, height)
226249

227-
class PerformScalabilityGridToMesh(PerformScalabilityGridToGrid):
250+
251+
@on_demand_benchmark
252+
class PerformScalabilityGridToMesh(PerformScalabilityMixin):
228253
regridder = GridToMeshESMFRegridder
229254

230255
def setup_cache(self):
@@ -242,11 +267,17 @@ def tgt_cube(self):
242267
tgt.add_aux_coord(mesh_coord_y, 0)
243268
return tgt
244269

270+
def time_perform(self, cache, height):
271+
super()._time_perform(cache, height)
272+
273+
def time_lazy_perform(self, cache, height):
274+
super()._time_lazy_perform(cache, height)
275+
245276

246277
# These benchmarks unusually long and are resource intensive so are skipped.
247278
# They can be run by manually removing the skip.
248279
@skip_benchmark
249-
class PerformScalability1kGridToGrid(PerformScalabilityGridToGrid):
280+
class PerformScalability1kGridToGrid(PerformScalabilityMixin):
250281
timeout = 600
251282
grid_size = 1100
252283
chunk_size = [grid_size, grid_size, 10]
@@ -259,11 +290,17 @@ class PerformScalability1kGridToGrid(PerformScalabilityGridToGrid):
259290
def setup_cache(self):
260291
return super().setup_cache()
261292

293+
def time_perform(self, cache, height):
294+
super()._time_perform(cache, height)
295+
296+
def time_lazy_perform(self, cache, height):
297+
super()._time_lazy_perform(cache, height)
298+
262299

263300
# These benchmarks unusually long and are resource intensive so are skipped.
264301
# They can be run by manually removing the skip.
265302
@skip_benchmark
266-
class PerformScalability2kGridToGrid(PerformScalabilityGridToGrid):
303+
class PerformScalability2kGridToGrid(PerformScalabilityMixin):
267304
timeout = 600
268305
grid_size = 2200
269306
chunk_size = [grid_size, grid_size, 10]
@@ -275,3 +312,9 @@ class PerformScalability2kGridToGrid(PerformScalabilityGridToGrid):
275312

276313
def setup_cache(self):
277314
return super().setup_cache()
315+
316+
def time_perform(self, cache, height):
317+
super()._time_perform(cache, height)
318+
319+
def time_lazy_perform(self, cache, height):
320+
super()._time_lazy_perform(cache, height)

noxfile.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@ def benchmarks(
475475
)
476476
publish_subdir.mkdir()
477477

478+
# Activate on demand benchmarks (C/SPerf are deactivated for 'standard' runs).
479+
session.env["ON_DEMAND_BENCHMARKS"] = "True"
478480
commit_range = "upstream/main^!"
479481

480482
asv_command = [

0 commit comments

Comments
 (0)