Skip to content

Cached benchmark file I/O - #1700

Draft
cmdupuis3 wants to merge 12 commits into
UXARRAY:mainfrom
cmdupuis3:cmd/bench_io
Draft

Cached benchmark file I/O#1700
cmdupuis3 wants to merge 12 commits into
UXARRAY:mainfrom
cmdupuis3:cmd/bench_io

Conversation

@cmdupuis3

@cmdupuis3 cmdupuis3 commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Closes #1698

Overview

This PR is a large-scale overhaul of the benchmarks to support single-loads of files per benchmark suite.

Currently, the ASV benchmark suite runs a new process per benchmark, requiring full-scale loads of files for every single benchmark. There are a limited number of files that are actually used to benchmark, so we end up loading many files dozens of times, running up wallclock time on the benchmark suite as a whole. This PR instead has a unified approach, where a parent process is launched for the whole benchmark suite, uncached files are retrieved into /uxarray/benchmarks/_io_cache/, and benchmarks are spawned on forked processes that inherit visibility into the file cache and some other properties.

Simultaneously, this reorganization of file I/O will help to expand the scope of what most non-I/O benchmarks are able to test, since some of them were artificially restricted to smaller grids. That raises another question about how many benchmarks really need to be run at every resolution, but I think that's out of scope for this PR, since it would alter the actual benchmark suite, rather than just changing how they are run.

General CI runs should see a wallclock improvement for whole benchmark suites. CI benchmark runs are showing improvements of about 19 minutes so far (38min -> 19min). Runs on HPC can expect larger improvements. Larger benchmark suites will benefit more from cached file I/O, while benchmarks run individually won't see much improvement.

Other general speed improvements:

  1. Test processes forking from warm-cache parent process
  2. Async dispatch of tests on file arrival, so large files don't stall tests of smaller files.
  3. Sample generation on parent process for reuse in forked processes; sacrifices a bit of robustness for significant speed gains in geometry routines.

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
  • Internal (private) function names start with an underscore (_)

AI Disclosure

AI Usage: Claude Opus 5

  • I take responsibility for all AI-generated content in my PR.
  • I have tested all AI-generated content in my PR.

@cmdupuis3 cmdupuis3 added scalability Related to scalability & performance efforts benchmarking Related to benchmarks, memory usage, and/or time profiling labels Aug 21, 2026
@cmdupuis3 cmdupuis3 self-assigned this Aug 21, 2026
@cmdupuis3 cmdupuis3 added the run-benchmark Run ASV benchmark workflow label Aug 21, 2026
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown

ASV Benchmarking

Benchmark Comparison Results

Benchmarks that have improved:

Change Before [c832ff1] After [6c2a7d8] Ratio Benchmark (Parameter)
* failed 8.07±0.08ms n/a face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
* failed 2.50±0.04ms n/a face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
* failed 9.30±10ms n/a face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
* failed 1.40±0.02ms n/a face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
* failed 57.3k n/a face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
* failed 12.3k n/a face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
* failed 123k n/a face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
* failed 128 n/a face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
* failed 1.27M n/a face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
* failed 50.1k n/a face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
* failed 1.48M n/a face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
* failed 712 n/a face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
* failed 1.97M n/a face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
* failed 1.96M n/a face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
* failed 2.12M n/a face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
* failed 35.5k n/a face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
- 431M 335M 0.78 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
- 441M 367M 0.83 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
- 431M 337M 0.78 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
- 431M 336M 0.78 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
- 11.4±0.04s 807±9ms 0.07 import.Imports.timeraw_import_uxarray
- 431M 293M 0.68 import.Imports.track_peakmem_import_uxarray
* failed 103±0.3ms n/a mpas_ocean.ConstructFaceLatLon.time_welzl('120km')
* failed 9.84±0.3ms n/a mpas_ocean.ConstructFaceLatLon.time_welzl('480km')
* failed 532±6ms n/a mpas_ocean.CrossSections.time_const_lat('120km', 1)
* failed 274±3ms n/a mpas_ocean.CrossSections.time_const_lat('120km', 2)
* failed 140±0.4ms n/a mpas_ocean.CrossSections.time_const_lat('120km', 4)
* failed 479±3ms n/a mpas_ocean.CrossSections.time_const_lat('480km', 1)
* failed 239±1ms n/a mpas_ocean.CrossSections.time_const_lat('480km', 2)
* failed 124±0.3ms n/a mpas_ocean.CrossSections.time_const_lat('480km', 4)
- 431M 355M 0.82 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 1)
- 431M 355M 0.82 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 2)
- 431M 355M 0.82 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 4)
- 431M 338M 0.78 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 1)
- 431M 338M 0.78 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 2)
- 431M 338M 0.78 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 4)
* failed 27.6±8ms n/a mpas_ocean.DualMesh.time_dual_mesh_construction('120km')
* failed 3.61±1ms n/a mpas_ocean.DualMesh.time_dual_mesh_construction('480km')
* failed 59.7±2ms n/a mpas_ocean.FaceAreas.time_face_areas('120km')
* failed 7.00±7ms n/a mpas_ocean.FaceAreas.time_face_areas('480km')
* failed 229k n/a mpas_ocean.FaceAreas.track_nbytes_face_areas('120km')
* failed 14.3k n/a mpas_ocean.FaceAreas.track_nbytes_face_areas('480km')
* failed 2.13M n/a mpas_ocean.FaceAreas.track_peakmem_face_areas('120km')
* failed 823k n/a mpas_ocean.FaceAreas.track_peakmem_face_areas('480km')
* failed 167±1ms n/a mpas_ocean.Gradient.time_gradient('120km')
* failed 11.1±0.04ms n/a mpas_ocean.Gradient.time_gradient('480km')
* failed 457k n/a mpas_ocean.Gradient.track_nbytes_gradient('120km')
* failed 28.7k n/a mpas_ocean.Gradient.track_nbytes_gradient('480km')
* failed 4.86M n/a mpas_ocean.Gradient.track_peakmem_gradient('120km')
* failed 313k n/a mpas_ocean.Gradient.track_peakmem_gradient('480km')
- 431M 351M 0.81 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('120km')
- 431M 330M 0.77 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('480km')
* failed 52.5±0.4ms n/a mpas_ocean.NeighborhoodDask.time_mean('120km', 'grid_chunks')
* failed 24.9±0.06ms n/a mpas_ocean.NeighborhoodDask.time_mean('120km', 'numpy')
* failed 49.1±1ms n/a mpas_ocean.NeighborhoodDask.time_mean('120km', 'time_chunks')
* failed 15.0±0.4ms n/a mpas_ocean.NeighborhoodDask.time_mean('480km', 'grid_chunks')
* failed 554±10μs n/a mpas_ocean.NeighborhoodDask.time_mean('480km', 'numpy')
* failed 11.0±0.3ms n/a mpas_ocean.NeighborhoodDask.time_mean('480km', 'time_chunks')
* failed 5.83M n/a mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'grid_chunks')
* failed 2.75M n/a mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'numpy')
* failed 5.67M n/a mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'time_chunks')
* failed 679k n/a mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'grid_chunks')
* failed 177k n/a mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'numpy')
* failed 529k n/a mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'time_chunks')
* failed 13.4±0.03s n/a mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'mean')
* failed 14.1±0s n/a mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'median')
* failed 245±1ms n/a mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'mean')
* failed 252±0.7ms n/a mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'median')
* failed 1.42±0s n/a mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'mean')
* failed 1.64±0s n/a mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'median')
* failed 27.8±0.3ms n/a mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'mean')
* failed 29.2±0.2ms n/a mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'median')
* failed 44.9±0.08ms n/a mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'mean')
* failed 260±0.8ms n/a mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'median')
* failed 680±60μs n/a mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'mean')
* failed 2.22±0.06ms n/a mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'median')
* failed 239k n/a mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('120km', 'mean')
* failed 245k n/a mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('120km', 'median')
* failed 19.4k n/a mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'mean')
* failed 19.9k n/a mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'median')
* failed 354±10μs n/a mpas_ocean.PointInPolygon.time_face_search_lonlat('120km')
* failed 326±10μs n/a mpas_ocean.PointInPolygon.time_face_search_lonlat('480km')
* failed 354±40μs n/a mpas_ocean.PointInPolygon.time_face_search_xyz('120km')
* failed 318±8μs n/a mpas_ocean.PointInPolygon.time_face_search_xyz('480km')
* failed 127±0.2ms n/a mpas_ocean.RemapDownsample.time_bilinear_remapping
* failed 1.09±0.01s n/a mpas_ocean.RemapUpsample.time_bilinear_remapping
* failed 8.93±0.03ms n/a mpas_ocean.ZonalAverage.time_zonal_average('120km')
* failed 4.53±0.1ms n/a mpas_ocean.ZonalAverage.time_zonal_average('480km')
- 431M 357M 0.83 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('120km')
- 431M 340M 0.79 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('480km')

Benchmarks that have stayed the same:

Change Before [c832ff1] After [6c2a7d8] Ratio Benchmark (Parameter)
200±0.5ms 217±9ms 1.08 bench_connectivity.Connectivity.time_edge_face('120km')
12.2±1ms 12.1±0.5ms 0.99 bench_connectivity.Connectivity.time_edge_face('480km')
198±1ms 206±10ms 1.04 bench_connectivity.Connectivity.time_edge_node('120km')
10.9±0.1ms 11.6±0.7ms 1.06 bench_connectivity.Connectivity.time_edge_node('480km')
198±1ms 207±9ms 1.04 bench_connectivity.Connectivity.time_face_edge('120km')
11.1±0.1ms 11.7±0.4ms 1.06 bench_connectivity.Connectivity.time_face_edge('480km')
797±4ms 804±20ms 1.01 bench_connectivity.Connectivity.time_face_face('120km')
49.5±0.6ms 49.8±0.8ms 1.01 bench_connectivity.Connectivity.time_face_face('480km')
45.9±0.3μs 44.9±7μs 0.98 bench_connectivity.Connectivity.time_face_node('120km')
44.4±0.6μs 44.0±1μs 0.99 bench_connectivity.Connectivity.time_face_node('480km')
343±6μs 341±7μs 0.99 bench_connectivity.Connectivity.time_n_nodes_per_face('120km')
261±9μs 260±9μs 1.00 bench_connectivity.Connectivity.time_n_nodes_per_face('480km')
199±0.5ms 207±10ms 1.04 bench_connectivity.Connectivity.time_node_edge('120km')
11.1±0.04ms 11.9±0.5ms 1.07 bench_connectivity.Connectivity.time_node_edge('480km')
80.2±5ms 81.2±6ms 1.01 bench_connectivity.Connectivity.time_node_face('120km')
4.86±0.06ms 4.75±0.1ms 0.98 bench_connectivity.Connectivity.time_node_face('480km')
1.14±0.02μs 1.10±0.03μs 0.96 geometry_kernels.AccucrossKernels.time_accucross
2.57±0.04μs 2.53±0.02μs 0.99 geometry_kernels.AccucrossKernels.time_accucross_pair
405±10ns 390±10ns 0.96 geometry_kernels.EFTPrimitives.time_acc_sqrt_re
411±20ns 386±8ns 0.94 geometry_kernels.EFTPrimitives.time_diff_of_products
361±20ns 341±9ns 0.94 geometry_kernels.EFTPrimitives.time_two_prod
345±5ns 480±200ns ~1.39 geometry_kernels.EFTPrimitives.time_two_sum
1.41±0.02μs 1.38±0.03μs 0.98 geometry_kernels.GCAConstLatIntersection.time_accux_constlat_kernel
1.06±0.02μs 1.02±0.01μs 0.96 geometry_kernels.GCAConstLatIntersection.time_gca_const_lat_intersection
1.79±0.03μs 1.79±0.04μs 1.00 geometry_kernels.GCAConstLatIntersection.time_try_gca_const_lat_intersection
1.56±0.02μs 1.54±0.03μs 0.99 geometry_kernels.GCAGCAIntersection.time_accux_gca_kernel
1.28±0.01μs 1.30±0.02μs 1.02 geometry_kernels.GCAGCAIntersection.time_gca_gca_intersection
2.03±0.03μs 2.05±0.05μs 1.01 geometry_kernels.GCAGCAIntersection.time_try_gca_gca_intersection
38.8±0.2μs 37.5±0.4μs 0.97 geometry_kernels.OrientPredicates.time_on_minor_arc
38.2±0.4μs 38.2±0.6μs 1.00 geometry_kernels.OrientPredicates.time_orient3d_on_sphere
3.02±0.01ms 2.79±0.01ms 0.92 geometry_samebody.SameBodyConstLat.time_accux_dispatch
1.32±0ms 1.33±0ms 1.01 geometry_samebody.SameBodyConstLat.time_accux_kernel
1.89±0.1ms 1.78±0.01ms 0.94 geometry_samebody.SameBodyConstLat.time_fp64_dispatch
149±0.2μs 149±0.2μs 1.00 geometry_samebody.SameBodyConstLat.time_fp64_kernel
32.8±0.2ms 32.4±0.2ms 0.99 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_dispatch
10.7±0.07ms 10.6±0.05ms 0.99 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_kernel
26.9±0.07ms 27.0±0.08ms 1.01 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_dispatch
4.68±0.2ms 4.38±0.04ms 0.94 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_kernel
2.12±0.06ms 2.02±0.01ms 0.95 mpas_ocean.CheckNorm.time_check_norm('120km')
1.60±0.01ms 1.58±0.01ms 0.99 mpas_ocean.CheckNorm.time_check_norm('480km')
733±20ms 718±9ms 0.98 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('120km')
45.5±0.5ms 45.3±0.3ms 1.00 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('480km')
582±5μs 576±8μs 0.99 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('120km')
515±8μs 513±10μs 1.00 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('480km')
5.03±0.06ms 4.97±0.02ms 0.99 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('120km')
3.54±0.01ms 3.47±0.06ms 0.98 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('480km')
20.0±0.07ms 19.9±0.04ms 1.00 mpas_ocean.ConstructTreeStructures.time_ball_tree('120km')
1.02±0.02ms 1.02±0.02ms 1.00 mpas_ocean.ConstructTreeStructures.time_ball_tree('480km')
11.0±0.04ms 11.0±0.04ms 1.00 mpas_ocean.ConstructTreeStructures.time_kd_tree('120km')
652±30μs 661±50μs 1.01 mpas_ocean.ConstructTreeStructures.time_kd_tree('480km')
853±4ms 851±4ms 1.00 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', False)
50.2±1ms 50.1±0.7ms 1.00 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', True)
74.3±0.7ms 74.5±1ms 1.00 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', False)
5.53±0.4ms 5.07±0.2ms 0.92 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', True)
266±6μs 273±5μs 1.03 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('120km')
134±5μs 131±2μs 0.98 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('480km')
195±9μs 190±2μs 0.97 mpas_ocean.Integrate.time_integrate('120km')
174±4μs 175±8μs 1.01 mpas_ocean.Integrate.time_integrate('480km')
18.4M 18.4M 1.00 mpas_ocean.Integrate.track_nbytes_integrate('120km')
1.2M 1.2M 1.00 mpas_ocean.Integrate.track_nbytes_integrate('480km')
186±1ms 188±0.9ms 1.01 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'exclude')
188±2ms 187±2ms 1.00 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'include')
188±1ms 187±0.8ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'split')
13.4±0.3ms 13.3±0.2ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'exclude')
13.3±0.4ms 13.2±0.09ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'include')
13.4±0.3ms 13.3±0.3ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'split')
258±0.5ms 259±0.4ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 1.0)
1.37±0s 1.37±0.01s 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 15.0)
532±0.9ms 533±1ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 5.0)
14.0±0.04ms 14.2±0.2ms 1.02 mpas_ocean.NeighborhoodBuild.time_build('480km', 1.0)
26.6±0.05ms 26.8±0.1ms 1.01 mpas_ocean.NeighborhoodBuild.time_build('480km', 15.0)
17.4±0.06ms 17.4±0.1ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('480km', 5.0)
254±1ms 253±0.1ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 1.0)
1.35±0s 1.35±0s 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 15.0)
527±1ms 529±2ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 5.0)
13.6±0.04ms 13.8±0.04ms 1.02 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 1.0)
26.2±0.04ms 26.4±0.3ms 1.01 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 15.0)
17.0±0.05ms 17.0±0.03ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 5.0)
1.19 1.19 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('120km', 1.0)
612.76 612.76 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('120km', 15.0)
74.17 74.17 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('120km', 5.0)
1.0 1.0 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('480km', 1.0)
37.29 37.29 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('480km', 15.0)
6.57 6.57 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('480km', 5.0)
728k 728k 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('120km', 1.0)
141M 141M 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('120km', 15.0)
17.4M 17.4M 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('120km', 5.0)
43k 43k 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('480km', 1.0)
563k 563k 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('480km', 15.0)
123k 123k 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('480km', 5.0)
5.72M 5.72M 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('120km', 1.0)
145M 145M 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('120km', 15.0)
21.5M 21.5M 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('120km', 5.0)
362k 362k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 1.0)
825k 825k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 15.0)
384k 384k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 5.0)
17.6±0.3ms 17.4±0.07ms 0.99 mpas_ocean.RemapDownsample.time_inverse_distance_weighted_remapping
15.4±0.3ms 15.6±0.06ms 1.01 mpas_ocean.RemapDownsample.time_nearest_neighbor_remapping
25.1±0.1ms 25.1±0.2ms 1.00 mpas_ocean.RemapUpsample.time_inverse_distance_weighted_remapping
10.9±0.04ms 10.9±0.07ms 1.00 mpas_ocean.RemapUpsample.time_nearest_neighbor_remapping
6.33±0.07ms 6.30±0.04ms 0.99 quad_hexagon.QuadHexagon.time_open_dataset
5.34±0.03ms 5.31±0.04ms 1.00 quad_hexagon.QuadHexagon.time_open_grid
408 408 1.00 quad_hexagon.QuadHexagon.track_nbytes_open_dataset
392 392 1.00 quad_hexagon.QuadHexagon.track_nbytes_open_grid
73k 73k 1.00 quad_hexagon.QuadHexagon.track_peakmem_open_dataset
72.1k 72.5k 1.01 quad_hexagon.QuadHexagon.track_peakmem_open_grid

@cmdupuis3

cmdupuis3 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

In timing the bench_connectivity.Connectivity suite on derecho, I'm finding that with this PR and a full _io_cache, the whole suite takes almost exactly an hour. On the main branch without this PR, just bench_connectivity.Connectivity.time_edge_face and time_face_edge take about 45 minutes each. The Connectivity suite has six tests in total, so the IO cache is actually not being used as extensively as it would be for a full benchmark suite.

asv preimports the benchmark suite before it runs any setup_cache
(asv/runner.py, spawner.preimport() ahead of the run loop), so on a cold
cache bench_connectivity's import-time preload_topologies is what fills
it -- serially, in the forkserver parent, before a single benchmark
starts. CachedFixtures.setup_cache then finds everything already built,
and prime(workers=...) never runs on the path it was written for.

Filling it from the CLI first puts those reads back in the parallel
prime. Worth a second or two on the GitHub runners, which only see the
oQU grids; worth rather more on a machine that can reach the four
dyamond grids on campaign storage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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 run-benchmark Run ASV benchmark workflow scalability Related to scalability & performance efforts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need a holistic approach to file I/O for benchmarks

1 participant