Skip to content

Cached benchmark file I/O - #1700

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

Cached benchmark file I/O#1700
cmdupuis3 wants to merge 23 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.

This PR has merged in PR #1708 already, since it is a precondition for the optimizations here to be thread-safe.

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 [38b33d8] After [6dfd6d5] Ratio Benchmark (Parameter)
- 346M 292M 0.84 import.Imports.track_peakmem_import_uxarray

Benchmarks that have stayed the same:

Change Before [38b33d8] After [6dfd6d5] Ratio Benchmark (Parameter)
4.95±0.04ms 4.85±0.02ms 0.98 bench_connectivity.Connectivity.time_edge_face('120km')
1.74±0.01ms 1.73±0.01ms 0.99 bench_connectivity.Connectivity.time_edge_face('480km')
3.96±0.03ms 3.93±0.03ms 0.99 bench_connectivity.Connectivity.time_edge_node('120km')
1.34±0.01ms 1.34±0.01ms 1.00 bench_connectivity.Connectivity.time_edge_node('480km')
3.99±0.03ms 4.00±0.02ms 1.00 bench_connectivity.Connectivity.time_face_edge('120km')
1.35±0.01ms 1.33±0.02ms 0.98 bench_connectivity.Connectivity.time_face_edge('480km')
5.70±0.06ms 5.63±0.06ms 0.99 bench_connectivity.Connectivity.time_face_face('120km')
2.03±0.01ms 2.02±0.02ms 0.99 bench_connectivity.Connectivity.time_face_face('480km')
45.5±7μs 44.9±1μs 0.99 bench_connectivity.Connectivity.time_face_node('120km')
44.7±0.4μs 44.4±1μs 0.99 bench_connectivity.Connectivity.time_face_node('480km')
385±6μs 382±5μs 0.99 bench_connectivity.Connectivity.time_n_nodes_per_face('120km')
316±5μs 305±10μs 0.97 bench_connectivity.Connectivity.time_n_nodes_per_face('480km')
5.33±0.03ms 5.26±0.04ms 0.99 bench_connectivity.Connectivity.time_node_edge('120km')
1.75±0.01ms 1.74±0.01ms 0.99 bench_connectivity.Connectivity.time_node_edge('480km')
88.7±20ms 83.7±5ms 0.94 bench_connectivity.Connectivity.time_node_face('120km')
4.77±0.09ms 4.72±0.03ms 0.99 bench_connectivity.Connectivity.time_node_face('480km')
7.57±0.1ms 7.34±0.08ms 0.97 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
2.39±0.06ms 2.36±0.06ms 0.99 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
10.6±10s 9.06±10ms ~0.00 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
1.36±0.04ms 1.30±0.03ms 0.96 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
57.3k 57.3k 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
12.3k 12.3k 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
123k 123k 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
128 128 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.27M 1.27M 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
50.1k 50.1k 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
1.48M 1.48M 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
712 712 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.98M 1.98M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
1.97M 1.97M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
2.13M 2.13M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
35.5k 35.5k 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
346M 336M 0.97 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
366M 366M 1.00 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
346M 338M 0.98 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
346M 337M 0.97 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.23±0.1μs 1.11±0.01μs ~0.90 geometry_kernels.AccucrossKernels.time_accucross
2.77±0.2μs 2.58±0.02μs 0.93 geometry_kernels.AccucrossKernels.time_accucross_pair
401±10ns 395±10ns 0.99 geometry_kernels.EFTPrimitives.time_acc_sqrt_re
410±20ns 416±10ns 1.01 geometry_kernels.EFTPrimitives.time_diff_of_products
350±20ns 366±20ns 1.04 geometry_kernels.EFTPrimitives.time_two_prod
361±10ns 360±20ns 1.00 geometry_kernels.EFTPrimitives.time_two_sum
606±10ns 611±10ns 1.01 geometry_kernels.GCAConstLatIntersection.time_accux_constlat_kernel
666±10ns 641±10ns 0.96 geometry_kernels.GCAConstLatIntersection.time_gca_const_lat_intersection
696±20ns 676±20ns 0.97 geometry_kernels.GCAConstLatIntersection.time_try_gca_const_lat_intersection
766±20ns 721±20ns 0.94 geometry_kernels.GCAGCAIntersection.time_accux_gca_kernel
826±20ns 842±20ns 1.02 geometry_kernels.GCAGCAIntersection.time_gca_gca_intersection
942±20ns 936±30ns 0.99 geometry_kernels.GCAGCAIntersection.time_try_gca_gca_intersection
37.1±0.3μs 36.3±0.2μs 0.98 geometry_kernels.OrientPredicates.time_on_minor_arc
37.5±0.4μs 36.6±0.4μs 0.97 geometry_kernels.OrientPredicates.time_orient3d_on_sphere
3.08±0.02ms 3.08±0.01ms 1.00 geometry_samebody.SameBodyConstLat.time_accux_dispatch
1.32±0ms 1.32±0ms 1.00 geometry_samebody.SameBodyConstLat.time_accux_kernel
2.07±0.01ms 2.07±0ms 1.00 geometry_samebody.SameBodyConstLat.time_fp64_dispatch
151±0.5μs 151±0.3μs 1.00 geometry_samebody.SameBodyConstLat.time_fp64_kernel
27.9±0.2ms 27.7±0.05ms 0.99 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_dispatch
6.80±0.02ms 6.79±0.02ms 1.00 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_kernel
21.0±0.05ms 20.9±0.01ms 1.00 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_dispatch
865±2μs 866±2μs 1.00 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_kernel
853±9ms 842±9ms 0.99 import.Imports.timeraw_import_uxarray
2.04±0.03ms 1.99±0.01ms 0.98 mpas_ocean.CheckNorm.time_check_norm('120km')
1.56±0.02ms 1.58±0.06ms 1.01 mpas_ocean.CheckNorm.time_check_norm('480km')
1.00±0ms 1.00±0.01ms 1.00 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('120km')
497±7μs 492±7μs 0.99 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('480km')
613±4μs 603±20μs 0.98 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('120km')
538±9μs 541±8μs 1.01 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('480km')
4.98±0.01ms 4.92±0ms 0.99 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('120km')
3.36±0.02ms 3.41±0.05ms 1.01 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('480km')
98.3±0.8ms 99.3±0.7ms 1.01 mpas_ocean.ConstructFaceLatLon.time_welzl('120km')
9.94±0.2ms 9.42±0.4ms 0.95 mpas_ocean.ConstructFaceLatLon.time_welzl('480km')
20.1±0.1ms 19.9±0.03ms 0.99 mpas_ocean.ConstructTreeStructures.time_ball_tree('120km')
1.00±0.02ms 1.03±0.03ms 1.03 mpas_ocean.ConstructTreeStructures.time_ball_tree('480km')
11.0±0.02ms 11.0±0.08ms 1.00 mpas_ocean.ConstructTreeStructures.time_kd_tree('120km')
643±6μs 640±10μs 1.00 mpas_ocean.ConstructTreeStructures.time_kd_tree('480km')
538±2ms 525±2ms 0.98 mpas_ocean.CrossSections.time_const_lat('120km', 1)
276±3ms 269±2ms 0.98 mpas_ocean.CrossSections.time_const_lat('120km', 2)
142±2ms 138±0.3ms 0.97 mpas_ocean.CrossSections.time_const_lat('120km', 4)
481±4ms 475±2ms 0.99 mpas_ocean.CrossSections.time_const_lat('480km', 1)
244±0.7ms 239±2ms 0.98 mpas_ocean.CrossSections.time_const_lat('480km', 2)
123±2ms 122±0.4ms 0.98 mpas_ocean.CrossSections.time_const_lat('480km', 4)
356M 356M 1.00 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 1)
356M 356M 1.00 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 2)
356M 356M 1.00 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 4)
346M 339M 0.98 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 1)
346M 339M 0.98 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 2)
346M 339M 0.98 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 4)
22.3±0.07ms 22.3±0.07ms 1.00 mpas_ocean.DualMesh.time_dual_mesh_construction('120km')
2.55±0.06ms 2.53±0.02ms 0.99 mpas_ocean.DualMesh.time_dual_mesh_construction('480km')
14.4±0.4ms 13.8±0.6ms 0.96 mpas_ocean.FaceAreas.time_face_areas('120km')
3.73±0.5ms 3.75±0.3ms 1.00 mpas_ocean.FaceAreas.time_face_areas('480km')
229k 229k 1.00 mpas_ocean.FaceAreas.track_nbytes_face_areas('120km')
14.3k 14.3k 1.00 mpas_ocean.FaceAreas.track_nbytes_face_areas('480km')
2.12M 2.12M 1.00 mpas_ocean.FaceAreas.track_peakmem_face_areas('120km')
729k 729k 1.00 mpas_ocean.FaceAreas.track_peakmem_face_areas('480km')
849±6ms 842±2ms 0.99 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', False)
52.3±2ms 51.1±1ms 0.98 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', True)
73.9±0.7ms 72.4±1ms 0.98 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', False)
5.20±0.3ms 4.85±0.1ms 0.93 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', True)
13.7±0.2ms 13.3±0.2ms 0.97 mpas_ocean.Gradient.time_gradient('120km')
1.68±0.01ms 1.70±0.08ms 1.01 mpas_ocean.Gradient.time_gradient('480km')
457k 457k 1.00 mpas_ocean.Gradient.track_nbytes_gradient('120km')
28.7k 28.7k 1.00 mpas_ocean.Gradient.track_nbytes_gradient('480km')
3.2M 3.2M 1.00 mpas_ocean.Gradient.track_peakmem_gradient('120km')
204k 204k 1.00 mpas_ocean.Gradient.track_peakmem_gradient('480km')
351M 351M 1.00 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('120km')
346M 331M 0.95 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('480km')
279±10μs 266±7μs 0.95 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('120km')
129±6μs 126±3μs 0.98 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('480km')
181±3μs 179±4μs 0.99 mpas_ocean.Integrate.time_integrate('120km')
164±2μs 166±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')
189±0.7ms 186±0.7ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'exclude')
190±1ms 190±2ms 1.00 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'include')
189±1ms 187±0.5ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'split')
13.8±0.06ms 13.2±0.1ms 0.96 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'exclude')
13.6±0.3ms 13.2±0.08ms 0.97 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'include')
13.8±0.08ms 13.2±0.03ms 0.96 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'split')
258±0.9ms 257±0.3ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 1.0)
1.37±0s 1.37±0s 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 15.0)
535±1ms 533±2ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 5.0)
14.1±0.02ms 14.0±0.05ms 0.99 mpas_ocean.NeighborhoodBuild.time_build('480km', 1.0)
26.8±0.1ms 26.5±0.07ms 0.99 mpas_ocean.NeighborhoodBuild.time_build('480km', 15.0)
17.3±0.04ms 17.4±0.1ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('480km', 5.0)
253±0.4ms 254±0.8ms 1.01 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)
528±0.7ms 527±0.8ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 5.0)
13.7±0.1ms 13.7±0.02ms 0.99 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 1.0)
26.4±0.08ms 26.3±0.03ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 15.0)
17.0±0.03ms 17.1±0.1ms 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)
48.1±0.3ms 47.6±0.6ms 0.99 mpas_ocean.NeighborhoodDask.time_mean('120km', 'grid_chunks')
24.9±0.1ms 25.0±0.03ms 1.00 mpas_ocean.NeighborhoodDask.time_mean('120km', 'numpy')
43.7±0.8ms 43.8±0.6ms 1.00 mpas_ocean.NeighborhoodDask.time_mean('120km', 'time_chunks')
11.4±0.2ms 10.9±0.2ms 0.96 mpas_ocean.NeighborhoodDask.time_mean('480km', 'grid_chunks')
634±30μs 630±10μs 0.99 mpas_ocean.NeighborhoodDask.time_mean('480km', 'numpy')
8.11±0.1ms 7.83±0.05ms 0.97 mpas_ocean.NeighborhoodDask.time_mean('480km', 'time_chunks')
5.84M 5.84M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'grid_chunks')
2.75M 2.75M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'numpy')
5.67M 5.67M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'time_chunks')
686k 752k 1.10 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'grid_chunks')
177k 176k 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'numpy')
528k 528k 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'time_chunks')
13.3±0.03s 13.3±0s 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'mean')
14.0±0.01s 14.0±0s 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'median')
239±0.5ms 238±1ms 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'mean')
247±1ms 244±0.8ms 0.99 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'median')
1.41±0s 1.41±0s 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'mean')
1.63±0s 1.63±0s 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'median')
27.3±0.2ms 27.4±0.2ms 1.01 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'mean')
28.8±0.2ms 28.7±0.2ms 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'median')
42.5±0.2ms 42.8±0.2ms 1.01 mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'mean')
259±0.6ms 259±0.7ms 1.00 mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'median')
607±20μs 610±20μs 1.00 mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'mean')
1.90±0.05ms 1.94±0.05ms 1.02 mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'median')
239k 239k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('120km', 'mean')
245k 245k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('120km', 'median')
19.4k 19.3k 0.99 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'mean')
19.9k 19.8k 0.99 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'median')
384±40μs 433±20μs ~1.13 mpas_ocean.PointInPolygon.time_face_search_lonlat('120km')
381±10μs 367±10μs 0.96 mpas_ocean.PointInPolygon.time_face_search_lonlat('480km')
375±20μs 390±30μs 1.04 mpas_ocean.PointInPolygon.time_face_search_xyz('120km')
345±8μs 357±10μs 1.04 mpas_ocean.PointInPolygon.time_face_search_xyz('480km')
124±0.8ms 121±0.5ms 0.97 mpas_ocean.RemapDownsample.time_bilinear_remapping
17.3±0.1ms 17.2±0.3ms 1.00 mpas_ocean.RemapDownsample.time_inverse_distance_weighted_remapping
15.6±0.1ms 15.5±0.1ms 0.99 mpas_ocean.RemapDownsample.time_nearest_neighbor_remapping
1.21±0s 1.22±0s 1.00 mpas_ocean.RemapUpsample.time_bilinear_remapping
26.2±0.1ms 26.3±0.7ms 1.00 mpas_ocean.RemapUpsample.time_inverse_distance_weighted_remapping
11.0±0.06ms 11.0±0.04ms 0.99 mpas_ocean.RemapUpsample.time_nearest_neighbor_remapping
8.11±0.1ms 8.18±0.2ms 1.01 mpas_ocean.ZonalAverage.time_zonal_average('120km')
4.86±0.07ms 4.78±0.06ms 0.98 mpas_ocean.ZonalAverage.time_zonal_average('480km')
358M 358M 1.00 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('120km')
346M 341M 0.99 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('480km')
6.32±0.06ms 6.37±0.08ms 1.01 quad_hexagon.QuadHexagon.time_open_dataset
5.28±0.08ms 5.42±0.2ms 1.03 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
73.1k 72.8k 0.99 quad_hexagon.QuadHexagon.track_peakmem_open_dataset
72.6k 71.8k 0.99 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