Skip to content
32 changes: 29 additions & 3 deletions benchmarks/face_bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path

import uxarray as ux
from .helpers._memsize import grid_nbytes

current_path = Path(os.path.dirname(os.path.realpath(__file__))).parents[0]

Expand All @@ -25,6 +26,31 @@ def time_face_bounds(self, grid_path):
"""Time to obtain ``Grid.face_bounds``"""
self.uxgrid.bounds

def peakmem_face_bounds(self, grid_path):
"""Peak memory usage obtain ``Grid.face_bounds."""
face_bounds = self.uxgrid.bounds
def track_nbytes_face_bounds(self, grid_path):
"""Size of the materialized ``Grid.face_bounds`` array."""
return self.uxgrid.bounds.nbytes

track_nbytes_face_bounds.unit = "bytes"

def track_nbytes_grid_with_bounds(self, grid_path):
"""Grid footprint after populating bounds -- catches cached arrays that
``bounds`` adds to the ``Grid`` beyond the returned array itself."""
self.uxgrid.bounds
return grid_nbytes(self.uxgrid)

track_nbytes_grid_with_bounds.unit = "bytes"


class FaceBoundsPeakMem:
"""Peak memory of a cold start: import uxarray, open a grid, get its bounds."""

params = FaceBounds.params
param_names = ["grid_path"]

def setup_cache(self):
"""Compile the njit kernels before anything is measured."""
for grid_path in self.params:
ux.open_grid(grid_path).bounds

def peakmem_open_and_bounds(self, grid_path):
ux.open_grid(grid_path).bounds
Empty file added benchmarks/helpers/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions benchmarks/helpers/_memsize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

__all__ = ["grid_nbytes", "dataset_nbytes"]


def grid_nbytes(uxgrid):
"""Total size of the arrays a ``Grid`` currently holds, in bytes."""
return uxgrid._ds.nbytes


def dataset_nbytes(uxds):
"""Total size of a ``UxDataset``, in bytes, including its grid."""
return uxds.nbytes + grid_nbytes(uxds.uxgrid)
4 changes: 4 additions & 0 deletions benchmarks/import.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ class Imports:

def timeraw_import_uxarray(self):
return "import uxarray"

def peakmem_import_uxarray(self):
"""Peak memory of a process that has imported uxarray."""
import uxarray # noqa: F401
57 changes: 48 additions & 9 deletions benchmarks/mpas_ocean.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import uxarray as ux

from .helpers._memsize import grid_nbytes

current_path = Path(os.path.dirname(os.path.realpath(__file__)))

data_var = 'bottomDepth'
Expand Down Expand Up @@ -57,27 +59,64 @@ def teardown(self, resolution, *args, **kwargs):


class FaceAreas(GridBenchmark):
def time_compute_face_areas(self, resolution):
self.uxgrid.compute_face_areas()
number = 1 # face_areas only calculates once before being cached

def setup(self, resolution, *args, **kwargs):
super().setup(resolution, *args, **kwargs)
del self.uxgrid._ds["face_areas"] # guarantee it is empty

def time_face_areas(self, resolution):
_ = self.uxgrid.face_areas

def peakmem_compute_face_areas(self, resolution):
self.uxgrid.compute_face_areas()
def track_nbytes_face_areas(self, resolution):
"""Size of the materialized ``Grid.face_areas`` array."""
return self.uxgrid.face_areas.nbytes

track_nbytes_face_areas.unit = "bytes"


class Gradient(DatasetBenchmark):
def time_gradient(self, resolution):
self.uxds[data_var].gradient()

def peakmem_gradient(self, resolution):
grad = self.uxds[data_var].gradient()
def track_nbytes_gradient(self, resolution):
"""Size of the gradient result."""
return self.uxds[data_var].gradient().nbytes

track_nbytes_gradient.unit = "bytes"


class Integrate(DatasetBenchmark):
def time_integrate(self, resolution):
self.uxds[data_var].integrate()

def peakmem_integrate(self, resolution):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no IntegratePeakMem class defined like others?

integral = self.uxds[data_var].integrate()
def track_nbytes_integrate(self, resolution):
"""Grid footprint after integrating."""
self.uxds[data_var].integrate()
return grid_nbytes(self.uxds.uxgrid)

track_nbytes_integrate.unit = "bytes"


class GradientPeakMem:
"""Peak memory of a cold start: import uxarray, open a dataset, take a gradient.

Not a :class:`DatasetBenchmark` subclass -- that would open the dataset in
``setup``, and asv counts setup memory towards ``peakmem_*``.
"""

param_names = ["resolution"]
params = [["480km", "120km"]]

def setup_cache(self):
"""Compile the njit kernels before anything is measured."""
for resolution in self.params[0]:
grid, data = file_path_dict[resolution]
ux.open_dataset(grid, data)[data_var].gradient()

def peakmem_gradient(self, resolution):
grid, data = file_path_dict[resolution]
ux.open_dataset(grid, data)[data_var].gradient()


class GeoDataFrame(DatasetBenchmark):
Expand All @@ -90,7 +129,7 @@ def time_to_geodataframe(self, resolution, exclude_antimeridian):

class ConnectivityConstruction(DatasetBenchmark):
def time_n_nodes_per_face(self, resolution):
self.uxds.uxgrid.n_nodes_per_face
_ = self.uxds.uxgrid.n_nodes_per_face

def time_face_face_connectivity(self, resolution):
ux.grid.connectivity._populate_face_face_connectivity(self.uxds.uxgrid)
Expand Down
22 changes: 9 additions & 13 deletions benchmarks/quad_hexagon.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path

import uxarray as ux
from .helpers._memsize import dataset_nbytes, grid_nbytes

current_path = Path(os.path.dirname(os.path.realpath(__file__))).parents[0]

Expand All @@ -14,23 +15,18 @@ def time_open_grid(self):
"""Time to open a `Grid`"""
ux.open_grid(grid_path)

# def mem_open_grid(self):
# """Memory Occupied by a `Grid`"""
# return ux.open_grid(grid_path)

def peakmem_open_grid(self):
"""Peak memory usage of a `Grid`"""
uxgrid = ux.open_grid(grid_path)
def track_nbytes_open_grid(self):
"""Memory occupied by a `Grid`"""
return grid_nbytes(ux.open_grid(grid_path))

track_nbytes_open_grid.unit = "bytes"

def time_open_dataset(self):
"""Time to open a `UxDataset`"""
ux.open_dataset(grid_path, data_path)

# def mem_open_dataset(self):
# """Memory occupied by a `UxDataset`"""
# return ux.open_dataset(grid_path, data_path)
def track_nbytes_open_dataset(self):
"""Memory occupied by a `UxDataset`, including its grid"""
return dataset_nbytes(ux.open_dataset(grid_path, data_path))

def peakmem_open_dataset(self):
"""Peak memory usage of a `UxDataset`"""
uxds = ux.open_dataset(grid_path, data_path)
track_nbytes_open_dataset.unit = "bytes"