Skip to content

Connectivity benchmarks cold-start - #1633

Open
cmdupuis3 wants to merge 2 commits into
UXARRAY:mainfrom
cmdupuis3:cmd/bench_connectivity_fix
Open

Connectivity benchmarks cold-start#1633
cmdupuis3 wants to merge 2 commits into
UXARRAY:mainfrom
cmdupuis3:cmd/bench_connectivity_fix

Conversation

@cmdupuis3

@cmdupuis3 cmdupuis3 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Closes #1632

Overview

This fix provides a bare-bones Grid that allows for properly cold timing of the connectivity benchmarks, aside from a numba warmup to remove that from timing results.

Example:

[50.00%] · For uxarray commit 5f0e401 <cmd/merge-OFE> (round 2/2):
[50.00%] ·· Benchmarking conda-py3.11-netcdf4-pip+pyfma-setuptools_scm-xarray
[75.00%] ··· bench_connectivity.Connectivity.time_edge_node ok
[75.00%] ··· ============ ==========
resolution
------------ ----------
480km 1.27±0ms
120km 3.99±0ms
30km 100±0ms
15km 434±0ms
7.5km 1.97±0s
3.75km 9.92±0s
============ ==========

PR Checklist

General

  • An issue is created and linked
  • Added appropriate labels (if your uxarray repo permissions allow it)
  • Filled out Overview and Expected Usage (if applicable) sections

Testing & Benchmarking

  • Adequate tests are created if there is new functionality
  • Tests are not too basic (such as simply calling a function and nothing else)
  • Tests cover all major paths in your new functions
  • If this PR could affect performance, ran ASV benchmarks and confirmed they show expected behavior (add a new benchmark if necessary)

Documentation

  • Docstrings have been added to all new functions
  • Docstrings have been updated with any function changes

@cmdupuis3 cmdupuis3 self-assigned this Jul 30, 2026
@cmdupuis3 cmdupuis3 added bug Something isn't working benchmarking Related to benchmarks, memory usage, and/or time profiling labels Jul 30, 2026
@cmdupuis3 cmdupuis3 added this to the Benchmarks milestone Jul 30, 2026
@cmdupuis3 cmdupuis3 added the run-benchmark Run ASV benchmark workflow label Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

ASV Benchmarking

Benchmark Comparison Results

Benchmarks that have improved:

Change Before [524015f] After [c0e1df9] Ratio Benchmark (Parameter)
- 526M 337M 0.64 face_bounds.FaceBounds.peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
- 640M 336M 0.53 face_bounds.FaceBounds.peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
- 452M 330M 0.73 mpas_ocean.Gradient.peakmem_gradient('480km')

Benchmarks that have stayed the same:

Change Before [524015f] After [c0e1df9] Ratio Benchmark (Parameter)
181±0.3ms 181±0.2ms 1 bench_connectivity.Connectivity.time_edge_face('120km')
10.5±0.05ms 10.4±0.04ms 1 bench_connectivity.Connectivity.time_edge_face('480km')
179±0.3ms 179±0.6ms 1 bench_connectivity.Connectivity.time_edge_node('120km')
10.0±0.2ms 9.83±0.06ms 0.98 bench_connectivity.Connectivity.time_edge_node('480km')
179±0.5ms 179±0.5ms 1 bench_connectivity.Connectivity.time_face_edge('120km')
10.0±0.04ms 9.97±0.02ms 1 bench_connectivity.Connectivity.time_face_edge('480km')
639±2ms 656±20ms 1.03 bench_connectivity.Connectivity.time_face_face('120km')
38.7±0.1ms 39.2±0.1ms 1.01 bench_connectivity.Connectivity.time_face_face('480km')
50.0±2μs 49.8±3μs 0.99 bench_connectivity.Connectivity.time_face_node('120km')
44.6±1μs 44.9±1μs 1.01 bench_connectivity.Connectivity.time_face_node('480km')
342±6μs 342±6μs 1 bench_connectivity.Connectivity.time_n_nodes_per_face('120km')
237±4μs 235±4μs 0.99 bench_connectivity.Connectivity.time_n_nodes_per_face('480km')
180±0.2ms 181±0.6ms 1 bench_connectivity.Connectivity.time_node_edge('120km')
9.99±0.05ms 10.3±0.3ms 1.03 bench_connectivity.Connectivity.time_node_edge('480km')
59.3±0.3ms 60.7±0.9ms 1.02 bench_connectivity.Connectivity.time_node_face('120km')
3.69±0.02ms 3.72±0.02ms 1.01 bench_connectivity.Connectivity.time_node_face('480km')
335M 335M 1 face_bounds.FaceBounds.peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
366M 366M 1 face_bounds.FaceBounds.peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
5.70±0.04ms 5.67±0.01ms 1 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
1.96±0.02ms 1.91±0.01ms 0.97 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
7.26±0ms 7.30±0.01ms 1.01 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
1.50±0.02ms 1.50±0.02ms 1 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
896±40ns 897±10ns 1 geometry_kernels.AccucrossKernels.time_accucross
1.99±0.02μs 2.01±0.01μs 1.01 geometry_kernels.AccucrossKernels.time_accucross_pair
311±10ns 310±8ns 1 geometry_kernels.EFTPrimitives.time_acc_sqrt_re
305±10ns 311±7ns 1.02 geometry_kernels.EFTPrimitives.time_diff_of_products
271±4ns 280±5ns 1.04 geometry_kernels.EFTPrimitives.time_two_prod
290±10ns 280±4ns 0.97 geometry_kernels.EFTPrimitives.time_two_sum
1.11±0.03μs 1.10±0.01μs 0.99 geometry_kernels.GCAConstLatIntersection.time_accux_constlat_kernel
797±10ns 791±40ns 0.99 geometry_kernels.GCAConstLatIntersection.time_gca_const_lat_intersection
1.40±0.01μs 1.35±0.01μs 0.97 geometry_kernels.GCAConstLatIntersection.time_try_gca_const_lat_intersection
1.20±0.03μs 1.20±0.02μs 1 geometry_kernels.GCAGCAIntersection.time_accux_gca_kernel
1.01±0.02μs 1.00±0.02μs 0.99 geometry_kernels.GCAGCAIntersection.time_gca_gca_intersection
1.56±0.04μs 1.58±0.02μs 1.01 geometry_kernels.GCAGCAIntersection.time_try_gca_gca_intersection
29.8±0.2μs 29.3±0.6μs 0.98 geometry_kernels.OrientPredicates.time_on_minor_arc
531±30ns 516±20ns 0.97 geometry_kernels.OrientPredicates.time_orient3d_on_sphere
2.27±0.08ms 2.17±0ms 0.96 geometry_samebody.SameBodyConstLat.time_accux_dispatch
1.02±0ms 1.02±0ms 1 geometry_samebody.SameBodyConstLat.time_accux_kernel
1.39±0.01ms 1.53±0.1ms 1.1 geometry_samebody.SameBodyConstLat.time_fp64_dispatch
120±0.8μs 120±2μs 1.01 geometry_samebody.SameBodyConstLat.time_fp64_kernel
26.7±0.5ms 25.7±0.04ms 0.96 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_dispatch
8.20±0.01ms 8.29±0.04ms 1.01 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_kernel
21.8±0.01ms 21.6±0.1ms 0.99 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_dispatch
3.57±0.01ms 3.40±0ms 0.95 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_kernel
613±2ms 610±2ms 1 import.Imports.timeraw_import_uxarray
1.81±0.01ms 1.76±0.02ms 0.98 mpas_ocean.CheckNorm.time_check_norm('120km')
1.40±0.02ms 1.38±0.01ms 0.99 mpas_ocean.CheckNorm.time_check_norm('480km')
558±2ms 553±9ms 0.99 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('120km')
35.0±0.1ms 34.9±0.1ms 1 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('480km')
512±10μs 520±8μs 1.02 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('120km')
425±8μs 419±9μs 0.99 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('480km')
3.48±0.02ms 3.50±0.01ms 1.01 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('120km')
2.69±0.03ms 2.67±0.02ms 0.99 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('480km')
2.59±0s 2.59±0.02s 1 mpas_ocean.ConstructFaceLatLon.time_welzl('120km')
164±0.6ms 166±0.9ms 1.01 mpas_ocean.ConstructFaceLatLon.time_welzl('480km')
15.3±0.02ms 15.3±0.02ms 1 mpas_ocean.ConstructTreeStructures.time_ball_tree('120km')
858±10μs 865±8μs 1.01 mpas_ocean.ConstructTreeStructures.time_ball_tree('480km')
8.23±0.02ms 8.23±0.01ms 1 mpas_ocean.ConstructTreeStructures.time_kd_tree('120km')
581±20μs 571±10μs 0.98 mpas_ocean.ConstructTreeStructures.time_kd_tree('480km')
505±3ms 509±1ms 1.01 mpas_ocean.CrossSections.time_const_lat('120km', 1)
263±4ms 256±0.6ms 0.97 mpas_ocean.CrossSections.time_const_lat('120km', 2)
133±0.4ms 133±0.2ms 1 mpas_ocean.CrossSections.time_const_lat('120km', 4)
373±1ms 376±3ms 1.01 mpas_ocean.CrossSections.time_const_lat('480km', 1)
189±0.3ms 191±0.3ms 1.01 mpas_ocean.CrossSections.time_const_lat('480km', 2)
97.9±0.7ms 97.6±0.2ms 1 mpas_ocean.CrossSections.time_const_lat('480km', 4)
16.8±0.06ms 16.9±0.06ms 1 mpas_ocean.DualMesh.time_dual_mesh_construction('120km')
1.96±0.02ms 1.98±0.01ms 1.01 mpas_ocean.DualMesh.time_dual_mesh_construction('480km')
655±4ms 641±1ms 0.98 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', False)
39.1±0.7ms 39.0±0.5ms 1 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', True)
56.0±0.1ms 55.7±0.2ms 0.99 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', False)
4.30±0.1ms 4.17±0.08ms 0.97 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', True)
351M 351M 1 mpas_ocean.Gradient.peakmem_gradient('120km')
130±6ms 130±6ms 1 mpas_ocean.Gradient.time_gradient('120km')
8.86±0.04ms 8.83±0.02ms 1 mpas_ocean.Gradient.time_gradient('480km')
283±6μs 277±4μs 0.98 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('120km')
145±4μs 146±5μs 1.01 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('480km')
350M 350M 1 mpas_ocean.Integrate.peakmem_integrate('120km')
329M 329M 1 mpas_ocean.Integrate.peakmem_integrate('480km')
435±5μs 438±20μs 1.01 mpas_ocean.Integrate.time_integrate('120km')
362±4μs 354±8μs 0.98 mpas_ocean.Integrate.time_integrate('480km')
145±0.8ms 145±0.7ms 1 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'exclude')
150±3ms 145±0.6ms 0.97 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'include')
147±0.8ms 146±3ms 1 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'split')
10.7±0.08ms 10.8±0.06ms 1.01 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'exclude')
10.7±0.06ms 10.7±0.1ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'include')
10.7±0.06ms 10.7±0.06ms 1 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'split')
271±5μs 273±7μs 1.01 mpas_ocean.PointInPolygon.time_face_search_lonlat('120km')
272±8μs 267±2μs 0.98 mpas_ocean.PointInPolygon.time_face_search_lonlat('480km')
258±8μs 257±8μs 1 mpas_ocean.PointInPolygon.time_face_search_xyz('120km')
245±7μs 244±9μs 1 mpas_ocean.PointInPolygon.time_face_search_xyz('480km')
165±0.6ms 162±0.4ms 0.98 mpas_ocean.RemapDownsample.time_bilinear_remapping
176±2ms 177±1ms 1.01 mpas_ocean.RemapDownsample.time_inverse_distance_weighted_remapping
12.0±0.03ms 11.9±0.02ms 0.99 mpas_ocean.RemapDownsample.time_nearest_neighbor_remapping
923±3ms 922±3ms 1 mpas_ocean.RemapUpsample.time_bilinear_remapping
36.4±0.2ms 36.2±0.3ms 0.99 mpas_ocean.RemapUpsample.time_inverse_distance_weighted_remapping
8.81±0.04ms 8.83±0.2ms 1 mpas_ocean.RemapUpsample.time_nearest_neighbor_remapping
21.0±0.4ms 21.5±0.1ms 1.02 mpas_ocean.ZonalAverage.time_zonal_average('120km')
4.04±0.04ms 4.11±0.03ms 1.02 mpas_ocean.ZonalAverage.time_zonal_average('480km')
325M 325M 1 quad_hexagon.QuadHexagon.peakmem_open_dataset
324M 324M 1 quad_hexagon.QuadHexagon.peakmem_open_grid
5.02±0.1ms 5.02±0.05ms 1 quad_hexagon.QuadHexagon.time_open_dataset
4.26±0.07ms 4.26±0.1ms 1 quad_hexagon.QuadHexagon.time_open_grid

@Sevans711
Sevans711 self-requested a review July 31, 2026 12:58

@Sevans711 Sevans711 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like a clean fix for these benchmarks. The run-benchmark results, along with the results reported in original message in PR thread, now all show expected scaling with grid size, rather than microsecond times regardless of grid size.

I considered whether it would make more sense to use Grid.__init__ with a dataset made up of just source_grid.node_lon, source_grid.node_lat, source_grid.face_node_connectivity, instead of using Grid.from_topology(), but then I realized that it shouldn't affect the timing of the benchmarks themselves, because that all happens directly in setup(), anyways.

So, looks good to me, no notes, my recommendation is to merge to main!

@cmdupuis3
cmdupuis3 requested review from dylannelson and rajeeja July 31, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

benchmarking Related to benchmarks, memory usage, and/or time profiling bug Something isn't working run-benchmark Run ASV benchmark workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connectivity benchmarks are a no-op

2 participants