Skip to content

Zarr I/O PR 7: real-world test data and benchmarks - #7349

Merged
pp-mo merged 18 commits into
SciTools:brownfieldfrom
trexfeathers:zarr-io-pr-7
Oct 27, 2026
Merged

pp-mo merged 18 commits into
SciTools:brownfieldfrom
trexfeathers:zarr-io-pr-7

Conversation

@trexfeathers

@trexfeathers trexfeathers commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

(posted by Claude Opus)

This is the seventh of nine pull requests delivering native Zarr support for Iris, and it adds the real-world test data and the ASV coverage the programme owes: a published NOAA GFS store loaded and saved by eleven integration tests, committed fixtures pinning fixed-length unicode on the read side, and Zarr added to the save, load and time-constraint benchmarks. Part of #6961. If the integration tests are wrong, Iris ships believing it reads published Zarr when it does not — and what I most want from a reviewer is a second opinion on dropping the EOPF fixture.

No library behaviour changes. Every file here is a test module, a benchmark, a workflow pin or a design document, with one exception: benchmarks/benchmarks/generate_data/um_files.py, which is benchmark support code and reaches no shipped module.

The base. This branch was built on zarr-io-pr-6 and previewed at trexfeathers#101, so its own diff could be read while #7346 was still in review; @pp-mo reviewed and approved it there, and his comments are answered in the commits here. #7346 has since merged, and this branch is now rebased onto brownfield with git rebase --onto upstream/brownfield zarr-io-pr-6 zarr-io-pr-7, so the diff below is this pull request's own work and nothing else.

The fixtures, and the version pin. The GFS store landed in SciTools/iris-test-data#98 and the stored unicode stores in #100, released together as v2.32, which both workflow files now pin — so every test here runs rather than skips. Locally against a v2.32 checkout the Zarr integration package is 86 passed with nothing skipped, and the whole suite is 12876 passed, 61 skipped, none failed. This branch was briefly red on purpose while #100 was still in review, so the new test could be read beside the fixtures it needs; that is over, and the version bump was the whole of the fix.

Important

The published GFS store names its CRS variable in coordinates and carries no grid_mapping attribute, so Iris builds no coordinate system from it and cube.coord("latitude").coord_system is None. CF section 5.6 makes grid_mapping the way a data variable points at its grid mapping, so Iris is already right and this branch changes nothing. A fallback that read crs_wkt off an unreferenced scalar coordinate was proposed and rejected by @trexfeathers: a library that second-guesses every file it might meet has given up the specification as the thing that decides. The behaviour is pinned by test so that the absent coordinate system reads as the data's doing rather than as a regression.

What is here

The data. A 1.4 MB subset of the dynamical.org NOAA GFS forecast archive, Zarr version 3, contributed to iris-test-data by SciTools/iris-test-data#98. It keeps the sharding codec, the scalar spatial_ref variable, the two-dimensional valid_time coordinate and the base64 _FillValue encoding, because those are what it exists to exercise. That pull request also teaches the index generator to treat a store as one item rather than descending into its chunks.

The integration tests. lib/iris/tests/integration/zarr/test_gfs_sample.py. Loading, the coordinate structure, the attribute handling, a round trip, and xarray opening what Iris wrote. Four of them pin behaviour no synthetic fixture in the package reaches: the grid-mapping finding above; an attribute literally named dtype, which is one of the names that used to be shadowed on load; mode="w" replacing an existing store, which was the one of the three save modes nothing covered; and a round trip dropping the source shard layout, which nothing promises to keep and nothing warns about.

Fixed-length unicode on the read side, twice. Before this branch every <U test in the package was on the write side. A unit test now writes a <U3 array with zarr-python and loads it back, on both Zarr versions; and an integration module reads two committed stores. The second exists because the first cannot pin what it looks like it pins — write and read move together when zarr-python's encoding moves, so only bytes that were written once and never touched again can show that Iris still reads a file written years ago. A test asserts the encoding strings those stores were written with, so regenerating them — which would destroy their only value — fails rather than passing quietly.

The benchmarks. The save benchmarks become one Save class parametrised over file_format, the shape LoadAndRealise and TimeConstraint already had, rather than a near-duplicate ZarrSave sitting beside NetcdfSave. Those two each grow a "Zarr" value beside their "NetCDF" one, and generate_data learns to write a store so they have something to load.

Where I would look first

The _assert_clean_load fixture in test_gfs_sample.py escalates IrisLoadWarning to an error and asserts LOAD_PROBLEMS is empty. That is only correct because the published store happens to load silently; if a future Iris starts recording a problem for it, this module fails rather than quietly covering it, which is the intent, but it does make the module strict.

Parametrising the save benchmarks renames the netCDF ones, so NetcdfSave.time_netcdf_save_cube becomes Save.time_save_cube and its ASV history does not carry across. That is a real loss, accepted on review as the lesser one against a near-duplicate class; it is the place I would most expect someone to disagree. time_save_mesh is guarded on the format rather than skipped, because ASV's skip facility raises out of setup() and so applies to every method in the class.

The save benchmarks pass mode="w". Without it the benchmark raises FileExistsError on its second call, because ASV re-runs a timing function many times between setup() calls and the Zarr saver defaults to mode="w-".

Both new modules skip on _shared_utils.skip_data alone. An earlier version also guarded on the store's own existence, because skip_data asks whether iris-test-data is present and never whether the file is — so on a checkout older than the pinned version these tests fail rather than skip, which is what the branch did on purpose while the fixtures were unreleased. Two reviewers objected from opposite sides and the custom guard went: it did not honour IRIS_TEST_NO_DATA, so keeping it would have run these tests for someone who had asked the suite not to touch external data. Iris and iris-test-data are versioned separately, so that window reopens whenever one moves first.

What I rejected

The ESA EOPF version 2 fixture, which the design document promised. Its licence is a bespoke Copernicus instrument rather than a standard one, and having it read by someone who handles Copernicus terms did not fit the schedule. Before dropping it I checked what it would have covered: the raise when a root group holds no data variables, the version 2 fill-value split, and nested JSON attributes are all already pinned by stores built in tmp_path. The one gap was reading a fixed-length unicode variable, which is the stored-fixture module above. The store stays in the design document as cited evidence for the rules it motivated; it goes only as a shipped fixture.

Replacing the synthetic GFS-like fixture with the real one, which fixtures.py said would happen. The synthetic store needs no external data, so it keeps test_load.py running where iris-test-data is absent, and it is the more CF-conforming of the two because it gives its data variable the grid_mapping attribute the published store lacks. The docstring is corrected rather than the fixture deleted.

Amending README.rst in iris-test-data. Its blanket Crown copyright claim has been inaccurate since a CC BY-SA 4.0 CMIP6 file landed there in 2019. That is a SciTools decision, raised as SciTools/iris-test-data#99; this work records provenance per directory instead.

No changelog fragment: per the design document, fragments are written once at merge-back.

trexfeathers and others added 15 commits October 27, 2026 12:15
Eleven tests over the published subset now in iris-test-data. Four of them
pin behaviour no synthetic fixture in this package reaches: the store names
its CRS variable in coordinates rather than grid_mapping, so no coordinate
system is built; it carries an attribute called dtype, one of the names that
used to be shadowed on load; mode='w' replaces an existing store, which was
the one of the three modes nothing covered; and a round trip drops the
source shard layout, which nothing promises to keep and nothing warns about.

Corrects the claim in fixtures.py that the real store replaces the synthetic
one. It does not: the synthetic store needs no external data, and it is the
more CF-conforming of the two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
Every <U test in this package was on the write side. SciTools#6961 records that
these dtypes are not strictly Zarr-supported, and the ESA EOPF Sentinel-2
products carry <U7 and <U3 arrays under conditions/geometry, so the read
side needs a defined answer rather than an accident. Covers version 2 and
version 3, since the two record dimension names differently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
ZarrSave mirrors NetcdfSave over the same cubesphere cubes, so the two
numbers are comparable. Two differences: it passes mode='w', because the
Zarr saver defaults to mode='w-' and raises FileExistsError on an existing
target while ASV calls a timing function many times between setup() calls;
and it has no mesh-only benchmark, because iris.mesh.save_mesh writes
netCDF only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
LoadAndRealise gains a Zarr file format beside its NetCDF one, so the two
are measured over the same synthetic UM data at the same shapes.

create_um_files needed two changes for it. Its reuse check tested is_file(),
which is always False for a store directory, so REUSE_DATA would never have
held and the data would have been rebuilt on every run. And compression is
spelled compressors= rather than zlib=: the Zarr saver rejects netCDF
keywords rather than translating them onto codecs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
Six findings, four of them things the published NOAA GFS store does that no
synthetic fixture did. The EOPF fixture is dropped on licence grounds and
sections 5 and 7 now say so; section 7 keeps the store as cited evidence,
because the rules it motivated do not depend on Iris shipping a copy.

Also adds the plan this pull request was built from.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
They failed instead. _shared_utils.skip_data asks only whether
iris-test-data is present at all, and get_data_path does not check that the
path it builds exists, so a checkout predating the store gave eleven
failures rather than eleven skips. Iris and iris-test-data are versioned
separately, so that window reopens whenever one moves before the other.

Also moves the xarray import into the one test that needs it, so an install
with zarr but without xarray loses that test rather than the whole module.

Corrects three things in the design document that this branch's own section
12.4 entry contradicts: section 7 called spatial_ref a grid mapping when the
store declares no grid_mapping attribute, said both sources are contributed
when only one is, and named the wrong fork. The header table said nothing
was blocked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
The published GFS store names its CRS variable in coordinates and declares
no grid_mapping attribute, so Iris builds no coordinate system from it. A
fallback reading crs_wkt off an unreferenced scalar coordinate was proposed
and rejected: section 1 already says a reader is never bent to fit one
publisher's files, and the specification is what decides. Section 12.4 now
records the decision rather than leaving the question open.

Records SciTools/iris-test-data#98 and #99 in section 12.1, and names #98 as
what the header table's Blocked on entry waits for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 511ac21a-e935-4d77-baa6-1b8cb42dac17
v2.31 is the first release holding test_data/Zarr/gfs_forecast_sample.zarr,
so until now the eleven integration tests over it skipped. Both workflow
files pin the version and the comment in ci-tests.yml points at the other.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
The GFS tests carried both a module skipif on the store's own existence and
the standard skip_data decorators. Reviewers objected from opposite sides,
and skip_data is the one to keep: it also honours IRIS_TEST_NO_DATA, which
the custom guard ignored, so keeping only the custom guard would have run
these tests for someone who had asked the suite not to touch external data.
The guard existed because the data was unreleased; iris-test-data v2.31 is
pinned now, and there is no backwards-compatibility contract with older
versions.

NetcdfSave and ZarrSave were near-identical, so they become one Save class
parametrised over file_format, the way LoadAndRealise and TimeConstraint
already are. time_save_mesh is guarded on the format rather than skipped,
because ASV's skip facility raises out of setup() and so cannot skip one
method for one parameter value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
No technical reason it was absent - the design document named LoadAndRealise
and the save benchmarks, so that is what was built. setup_cache already
passes the format list straight to create_um_files, so this is one word.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
…in them

Section 6 gains the rule the review turned up: a test that writes an array
and reads it back moves when the writing library moves, so it answers the
reader-against-writer question and not the interoperability one. That needs
bytes which do not move, which is SciTools/iris-test-data#100.

Section 12.4 records the three other review actions, and 12.1 and 12.5 carry
the new companion pull request.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
The unit test for <U dtypes writes an array with zarr-python and reads it
back with Iris, so both halves move whenever zarr-python's encoding moves:
change it and the test still passes while a file written years earlier stops
loading. That is the reader-against-writer question, not the one <U support
actually answers. These stores were written once and committed, so they pin
the second.

One of the tests asserts the on-disk dtype strings, so regenerating the
fixtures - which would destroy their only value - fails rather than passing
quietly.

These tests FAIL until SciTools/iris-test-data#100 merges, releases, and
IRIS_TEST_DATA_VERSION is bumped. Committed red deliberately, so that the
new file can be reviewed alongside the fixtures it reads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: 0022a6ec-642a-4844-ae3b-6b8f4421303a
@trexfeathers trexfeathers added Agentic Type: Feature Branch Highlight this for a feature branch labels Oct 27, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: c18b0b04-01bf-4ba9-96b0-4d8c8b5cfa02
trexfeathers and others added 2 commits October 27, 2026 12:35
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: c18b0b04-01bf-4ba9-96b0-4d8c8b5cfa02
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Session-Id: c18b0b04-01bf-4ba9-96b0-4d8c8b5cfa02
@codecov

codecov Bot commented Oct 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.03%. Comparing base (2548395) to head (93eaede).

Additional details and impacted files
@@             Coverage Diff             @@
##           brownfield    #7349   +/-   ##
===========================================
  Coverage       91.03%   91.03%           
===========================================
  Files             106      106           
  Lines           27148    27148           
  Branches         4961     4961           
===========================================
  Hits            24715    24715           
  Misses           1677     1677           
  Partials          756      756           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@trexfeathers trexfeathers added the benchmark_this Request that this pull request be benchmarked to check if it introduces performance shifts label Oct 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⏱️ Performance Benchmark Report: 4966a51

Performance shifts

Full benchmark results

Benchmarks that have stayed the same:

| Change   | Before [25483956]    | After [4966a51a]    |   Ratio | Benchmark (Parameter)                                                                       |
|----------|----------------------|---------------------|---------|---------------------------------------------------------------------------------------------|
|          | 20.6±0.2ms           | 21.0±0.5ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_COUNT(False)                              |
|          | 52.1±0.7ms           | 52.0±0.7ms          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_COUNT(True)                               |
|          | 34.3±0.2ms           | 34.4±0.8ms          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_FAST_PERCENTILE(False)                    |
|          | 164±2ms              | 163±1ms             |    1    | aggregate_collapse.Aggregation.time_aggregated_by_FAST_PERCENTILE(True)                     |
|          | 22.7±0.2ms           | 22.5±0.5ms          |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_GMEAN(False)                              |
|          | 32.0±2ms             | 31.4±0.5ms          |    0.98 | aggregate_collapse.Aggregation.time_aggregated_by_GMEAN(True)                               |
|          | 22.6±0.2ms           | 22.9±0.7ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_HMEAN(False)                              |
|          | 32.0±0.5ms           | 31.7±2ms            |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_HMEAN(True)                               |
|          | 20.4±0.1ms           | 20.5±0.2ms          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_MAX(False)                                |
|          | 43.5±0.6ms           | 42.9±0.5ms          |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_MAX(True)                                 |
|          | 131±0.6ms            | 134±0.5ms           |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_MAX_RUN(False)                            |
|          | 133±2ms              | 133±1ms             |    1    | aggregate_collapse.Aggregation.time_aggregated_by_MAX_RUN(True)                             |
|          | 21.7±0.4ms           | 21.5±0.1ms          |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_MEAN(False)                               |
|          | 47.7±0.3ms           | 48.0±0.8ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_MEAN(True)                                |
|          | 22.8±0.7ms           | 22.9±0.2ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_MEDIAN(False)                             |
|          | 57.4±0.7ms           | 57.4±0.5ms          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_MEDIAN(True)                              |
|          | 20.5±0.5ms           | 20.4±0.3ms          |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_MIN(False)                                |
|          | 43.5±0.9ms           | 43.2±0.7ms          |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_MIN(True)                                 |
|          | 1.15±0.01s           | 1.15±0.01s          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_PEAK(False)                               |
|          | 1.07±0s              | 1.08±0.07s          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_PEAK(True)                                |
|          | 223±2ms              | 219±1ms             |    0.98 | aggregate_collapse.Aggregation.time_aggregated_by_PERCENTILE(False)                         |
|          | 368±9ms              | 365±10ms            |    0.99 | aggregate_collapse.Aggregation.time_aggregated_by_PERCENTILE(True)                          |
|          | 21.3±0.1ms           | 21.7±0.3ms          |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_PROPORTION(False)                         |
|          | 30.0±0.6ms           | 30.5±0.5ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_PROPORTION(True)                          |
|          | 22.2±0.6ms           | 21.8±0.3ms          |    0.98 | aggregate_collapse.Aggregation.time_aggregated_by_RMS(False)                                |
|          | 57.5±1ms             | 57.2±0.5ms          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_RMS(True)                                 |
|          | 22.7±0.2ms           | 22.7±0.09ms         |    1    | aggregate_collapse.Aggregation.time_aggregated_by_STD_DEV(False)                            |
|          | 60.8±0.6ms           | 61.7±1ms            |    1.02 | aggregate_collapse.Aggregation.time_aggregated_by_STD_DEV(True)                             |
|          | 22.6±0.1ms           | 22.8±0.4ms          |    1.01 | aggregate_collapse.Aggregation.time_aggregated_by_VARIANCE(False)                           |
|          | 57.1±1ms             | 57.3±0.5ms          |    1    | aggregate_collapse.Aggregation.time_aggregated_by_VARIANCE(True)                            |
|          | 7.66±0.03ms          | 7.65±0.08ms         |    1    | aggregate_collapse.Aggregation.time_collapsed_by_COUNT(False)                               |
|          | 21.1±0.3ms           | 22.2±0.5ms          |    1.05 | aggregate_collapse.Aggregation.time_collapsed_by_COUNT(True)                                |
|          | 19.3±0.3ms           | 19.3±0.08ms         |    1    | aggregate_collapse.Aggregation.time_collapsed_by_FAST_PERCENTILE(False)                     |
|          | 122±2ms              | 120±2ms             |    0.99 | aggregate_collapse.Aggregation.time_collapsed_by_FAST_PERCENTILE(True)                      |
|          | 8.12±0.05ms          | 8.12±0.07ms         |    1    | aggregate_collapse.Aggregation.time_collapsed_by_GMEAN(False)                               |
|          | 19.5±0.3ms           | 20.3±0.5ms          |    1.04 | aggregate_collapse.Aggregation.time_collapsed_by_GMEAN(True)                                |
|          | 8.01±0.05ms          | 8.06±0.06ms         |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_HMEAN(False)                               |
|          | 19.5±0.1ms           | 20.1±0.7ms          |    1.03 | aggregate_collapse.Aggregation.time_collapsed_by_HMEAN(True)                                |
|          | 7.52±0.06ms          | 7.64±0.05ms         |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MAX(False)                                 |
|          | 19.9±0.3ms           | 20.1±0.4ms          |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_MAX(True)                                  |
|          | 25.6±0.5ms           | 25.5±0.4ms          |    1    | aggregate_collapse.Aggregation.time_collapsed_by_MAX_RUN(False)                             |
|          | 35.0±0.8ms           | 34.8±0.8ms          |    0.99 | aggregate_collapse.Aggregation.time_collapsed_by_MAX_RUN(True)                              |
|          | 7.91±0.05ms          | 7.83±0.05ms         |    0.99 | aggregate_collapse.Aggregation.time_collapsed_by_MEAN(False)                                |
|          | 20.6±0.3ms           | 20.6±0.4ms          |    1    | aggregate_collapse.Aggregation.time_collapsed_by_MEAN(True)                                 |
|          | 8.87±0.1ms           | 8.83±0.04ms         |    1    | aggregate_collapse.Aggregation.time_collapsed_by_MEDIAN(False)                              |
|          | 22.6±0.4ms           | 22.6±0.6ms          |    1    | aggregate_collapse.Aggregation.time_collapsed_by_MEDIAN(True)                               |
|          | 7.50±0.03ms          | 7.59±0.04ms         |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_MIN(False)                                 |
|          | 19.8±0.1ms           | 20.3±0.6ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_MIN(True)                                  |
|          | 578±1ms              | 580±4ms             |    1    | aggregate_collapse.Aggregation.time_collapsed_by_PEAK(False)                                |
|          | 575±0.9ms            | 575±2ms             |    1    | aggregate_collapse.Aggregation.time_collapsed_by_PEAK(True)                                 |
|          | 46.3±0.7ms           | 46.1±0.5ms          |    0.99 | aggregate_collapse.Aggregation.time_collapsed_by_PERCENTILE(False)                          |
|          | 135±2ms              | 138±4ms             |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_PERCENTILE(True)                           |
|          | 7.90±0.05ms          | 7.93±0.05ms         |    1    | aggregate_collapse.Aggregation.time_collapsed_by_PROPORTION(False)                          |
|          | 19.2±0.4ms           | 19.5±0.4ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_PROPORTION(True)                           |
|          | 7.83±0.04ms          | 7.90±0.1ms          |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_RMS(False)                                 |
|          | 21.8±0.4ms           | 22.3±0.5ms          |    1.02 | aggregate_collapse.Aggregation.time_collapsed_by_RMS(True)                                  |
|          | 8.13±0.07ms          | 8.14±0.08ms         |    1    | aggregate_collapse.Aggregation.time_collapsed_by_STD_DEV(False)                             |
|          | 21.5±0.3ms           | 21.5±0.4ms          |    1    | aggregate_collapse.Aggregation.time_collapsed_by_STD_DEV(True)                              |
|          | 8.12±0.04ms          | 8.21±0.08ms         |    1.01 | aggregate_collapse.Aggregation.time_collapsed_by_VARIANCE(False)                            |
|          | 21.1±0.2ms           | 21.1±0.5ms          |    1    | aggregate_collapse.Aggregation.time_collapsed_by_VARIANCE(True)                             |
|          | 22.5±0.3ms           | 22.4±0.6ms          |    1    | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_MEAN(False)                     |
|          | 82.1±0.8ms           | 82.3±0.7ms          |    1    | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_MEAN(True)                      |
|          | 22.1±0.2ms           | 22.0±0.3ms          |    1    | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_RMS(False)                      |
|          | 94.2±1ms             | 93.6±1ms            |    0.99 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_RMS(True)                       |
|          | 20.9±0.1ms           | 21.2±0.5ms          |    1.01 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_SUM(False)                      |
|          | 53.3±0.6ms           | 54.1±0.6ms          |    1.01 | aggregate_collapse.WeightedAggregation.time_w_aggregated_by_SUM(True)                       |
|          | 8.24±0.05ms          | 8.29±0.06ms         |    1.01 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_MEAN(False)                      |
|          | 26.5±0.6ms           | 27.0±0.7ms          |    1.02 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_MEAN(True)                       |
|          | 7.96±0.05ms          | 8.10±0.1ms          |    1.02 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_RMS(False)                       |
|          | 27.8±0.4ms           | 28.9±0.6ms          |    1.04 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_RMS(True)                        |
|          | 7.77±0.05ms          | 7.79±0.04ms         |    1    | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_SUM(False)                       |
|          | 21.9±0.2ms           | 21.8±0.3ms          |    1    | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_SUM(True)                        |
|          | 207±2ms              | 205±1ms             |    0.99 | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_WPERCENTILE(False)               |
|          | 270±2ms              | 271±1ms             |    1    | aggregate_collapse.WeightedAggregation.time_w_collapsed_by_WPERCENTILE(True)                |
|          | 1.21±0.01ms          | 1.21±0.01ms         |    0.99 | cube.CubeCreation.time_create(False, 'construct')                                           |
|          | 475±9μs              | 462±20μs            |    0.97 | cube.CubeCreation.time_create(False, 'instantiate')                                         |
|          | 1.92±0.02ms          | 1.96±0.04ms         |    1.02 | cube.CubeCreation.time_create(True, 'construct')                                            |
|          | 1.37±0.02ms          | 1.38±0.02ms         |    1.01 | cube.CubeCreation.time_create(True, 'instantiate')                                          |
|          | 81.6±2ms             | 81.5±3ms            |    1    | cube.CubeEquality.time_equality(False, False, 'all_equal')                                  |
|          | 26.1±0.8ms           | 26.3±1ms            |    1.01 | cube.CubeEquality.time_equality(False, False, 'coord_inequality')                           |
|          | 93.5±1ms             | 92.5±1ms            |    0.99 | cube.CubeEquality.time_equality(False, False, 'data_inequality')                            |
|          | 62.8±2μs             | 67.6±4μs            |    1.08 | cube.CubeEquality.time_equality(False, False, 'metadata_inequality')                        |
|          | 83.3±0.8ms           | 84.8±2ms            |    1.02 | cube.CubeEquality.time_equality(False, True, 'all_equal')                                   |
|          | 29.1±0.3ms           | 28.9±0.9ms          |    0.99 | cube.CubeEquality.time_equality(False, True, 'coord_inequality')                            |
|          | 95.3±2ms             | 97.7±2ms            |    1.03 | cube.CubeEquality.time_equality(False, True, 'data_inequality')                             |
|          | 62.7±2μs             | 60.8±2μs            |    0.97 | cube.CubeEquality.time_equality(False, True, 'metadata_inequality')                         |
|          | 157±4ms              | 161±3ms             |    1.03 | cube.CubeEquality.time_equality(True, False, 'all_equal')                                   |
|          | 64.0±2ms             | 64.8±1ms            |    1.01 | cube.CubeEquality.time_equality(True, False, 'coord_inequality')                            |
|          | 186±5ms              | 186±3ms             |    1    | cube.CubeEquality.time_equality(True, False, 'data_inequality')                             |
|          | 86.8±1μs             | 86.4±5μs            |    1    | cube.CubeEquality.time_equality(True, False, 'metadata_inequality')                         |
|          | 231±3ms              | 232±3ms             |    1    | cube.CubeEquality.time_equality(True, True, 'all_equal')                                    |
|          | 138±3ms              | 137±0.7ms           |    0.99 | cube.CubeEquality.time_equality(True, True, 'coord_inequality')                             |
|          | 257±7ms              | 261±4ms             |    1.01 | cube.CubeEquality.time_equality(True, True, 'data_inequality')                              |
|          | 379±10μs             | 388±8μs             |    1.02 | cube.CubeEquality.time_equality(True, True, 'metadata_inequality')                          |
|          | 850±3μs              | 845±5μs             |    0.99 | import_iris.Iris.time__concatenate                                                          |
|          | 184±1μs              | 185±3μs             |    1.01 | import_iris.Iris.time__constraints                                                          |
|          | 115±0.6μs            | 117±1μs             |    1.01 | import_iris.Iris.time__data_manager                                                         |
|          | 100±1μs              | 101±1μs             |    1    | import_iris.Iris.time__deprecation                                                          |
|          | 168±2μs              | 169±2μs             |    1.01 | import_iris.Iris.time__lazy_data                                                            |
|          | 978±10μs             | 971±8μs             |    0.99 | import_iris.Iris.time__merge                                                                |
|          | 74.0±0.4μs           | 73.7±0.5μs          |    1    | import_iris.Iris.time__representation                                                       |
|          | 618±3μs              | 627±30μs            |    1.01 | import_iris.Iris.time_analysis                                                              |
|          | 142±0.7μs            | 141±3μs             |    0.99 | import_iris.Iris.time_analysis__area_weighted                                               |
|          | 123±0.8μs            | 125±2μs             |    1.01 | import_iris.Iris.time_analysis__grid_angles                                                 |
|          | 253±1μs              | 255±4μs             |    1.01 | import_iris.Iris.time_analysis__interpolation                                               |
|          | 196±4μs              | 191±5μs             |    0.97 | import_iris.Iris.time_analysis__regrid                                                      |
|          | 110±0.6μs            | 110±2μs             |    1    | import_iris.Iris.time_analysis__scipy_interpolate                                           |
|          | 140±1μs              | 144±0.9μs           |    1.03 | import_iris.Iris.time_analysis_calculus                                                     |
|          | 336±2μs              | 337±5μs             |    1    | import_iris.Iris.time_analysis_cartography                                                  |
|          | 92.4±0.5μs           | 91.9±0.3μs          |    0.99 | import_iris.Iris.time_analysis_geomerty                                                     |
|          | 209±2μs              | 211±2μs             |    1.01 | import_iris.Iris.time_analysis_maths                                                        |
|          | 95.2±0.7μs           | 95.4±0.6μs          |    1    | import_iris.Iris.time_analysis_stats                                                        |
|          | 170±2μs              | 173±3μs             |    1.02 | import_iris.Iris.time_analysis_trajectory                                                   |
|          | 318±1μs              | 319±10μs            |    1    | import_iris.Iris.time_aux_factory                                                           |
|          | 80.6±0.5μs           | 80.6±0.9μs          |    1    | import_iris.Iris.time_common                                                                |
|          | 156±1μs              | 158±3μs             |    1.02 | import_iris.Iris.time_common_lenient                                                        |
|          | 1.54±0.01ms          | 1.55±0.02ms         |    1.01 | import_iris.Iris.time_common_metadata                                                       |
|          | 176±2μs              | 178±4μs             |    1.01 | import_iris.Iris.time_common_mixin                                                          |
|          | 1.17±0.01ms          | 1.17±0.01ms         |    1    | import_iris.Iris.time_common_resolve                                                        |
|          | 252±2μs              | 257±2μs             |    1.02 | import_iris.Iris.time_config                                                                |
|          | 135±0.5μs            | 132±2μs             |    0.98 | import_iris.Iris.time_coord_categorisation                                                  |
|          | 369±2μs              | 381±5μs             |    1.03 | import_iris.Iris.time_coord_systems                                                         |
|          | 815±8μs              | 827±6μs             |    1.01 | import_iris.Iris.time_coords                                                                |
|          | 726±5μs              | 736±10μs            |    1.01 | import_iris.Iris.time_cube                                                                  |
|          | 261±1μs              | 263±4μs             |    1.01 | import_iris.Iris.time_exceptions                                                            |
|          | 75.2±1μs             | 74.0±2μs            |    0.98 | import_iris.Iris.time_experimental                                                          |
|          | 204±1μs              | 206±1μs             |    1.01 | import_iris.Iris.time_fileformats                                                           |
|          | 253±5μs              | 254±5μs             |    1.01 | import_iris.Iris.time_fileformats__ff                                                       |
|          | 2.71±0.03ms          | 2.77±0.05ms         |    1.02 | import_iris.Iris.time_fileformats__ff_cross_references                                      |
|          | 75.3±0.5μs           | 76.6±0.3μs          |    1.02 | import_iris.Iris.time_fileformats__pp_lbproc_pairs                                          |
|          | 114±0.4μs            | 114±1μs             |    1    | import_iris.Iris.time_fileformats_abf                                                       |
|          | 85.6±0.6μs           | 85.6±0.6μs          |    1    | import_iris.Iris.time_fileformats_cf                                                        |
|          | 4.52±0.02ms          | 4.61±0.3ms          |    1.02 | import_iris.Iris.time_fileformats_dot                                                       |
|          | 70.3±0.3μs           | 71.9±0.3μs          |    1.02 | import_iris.Iris.time_fileformats_name                                                      |
|          | 252±1μs              | 255±2μs             |    1.01 | import_iris.Iris.time_fileformats_name_loaders                                              |
|          | 120±1μs              | 120±0.7μs           |    1    | import_iris.Iris.time_fileformats_netcdf                                                    |
|          | 162±2μs              | 162±2μs             |    1    | import_iris.Iris.time_fileformats_nimrod                                                    |
|          | 319±6μs              | 325±1μs             |    1.02 | import_iris.Iris.time_fileformats_nimrod_load_rules                                         |
|          | 798±8μs              | 803±10μs            |    1.01 | import_iris.Iris.time_fileformats_pp                                                        |
|          | 175±2μs              | 176±3μs             |    1    | import_iris.Iris.time_fileformats_pp_load_rules                                             |
|          | 135±0.8μs            | 134±0.7μs           |    1    | import_iris.Iris.time_fileformats_pp_save_rules                                             |
|          | 565±3μs              | 567±3μs             |    1    | import_iris.Iris.time_fileformats_rules                                                     |
|          | 226±3μs              | 226±3μs             |    1    | import_iris.Iris.time_fileformats_structured_array_identification                           |
|          | 80.3±0.3μs           | 79.3±1μs            |    0.99 | import_iris.Iris.time_fileformats_um                                                        |
|          | 159±1μs              | 160±3μs             |    1.01 | import_iris.Iris.time_fileformats_um__fast_load                                             |
|          | 141±3μs              | 140±2μs             |    0.99 | import_iris.Iris.time_fileformats_um__fast_load_structured_fields                           |
|          | 72.5±0.8μs           | 72.2±0.2μs          |    1    | import_iris.Iris.time_fileformats_um__ff_replacement                                        |
|          | 78.8±0.4μs           | 78.0±0.3μs          |    0.99 | import_iris.Iris.time_fileformats_um__optimal_array_structuring                             |
|          | 990±7μs              | 988±6μs             |    1    | import_iris.Iris.time_fileformats_um_cf_map                                                 |
|          | 157±2μs              | 159±2μs             |    1.02 | import_iris.Iris.time_io                                                                    |
|          | 183±2μs              | 185±3μs             |    1.01 | import_iris.Iris.time_io_format_picker                                                      |
|          | 203±1μs              | 206±3μs             |    1.02 | import_iris.Iris.time_iris                                                                  |
|          | 125±1μs              | 126±0.9μs           |    1.01 | import_iris.Iris.time_iterate                                                               |
|          | 8.45±0.05ms          | 8.59±0.2ms          |    1.02 | import_iris.Iris.time_palette                                                               |
|          | 1.89±0.02ms          | 1.88±0.09ms         |    0.99 | import_iris.Iris.time_plot                                                                  |
|          | 261±20μs             | 265±20μs            |    1.02 | import_iris.Iris.time_quickplot                                                             |
|          | 2.20±0.01ms          | 2.19±0.01ms         |    1    | import_iris.Iris.time_std_names                                                             |
|          | 1.83±0.01ms          | 1.90±0.1ms          |    1.04 | import_iris.Iris.time_symbols                                                               |
|          | 24.9±1ms             | 24.7±1ms            |    0.99 | import_iris.Iris.time_tests                                                                 |
|          | 251±2μs              | 253±2μs             |    1.01 | import_iris.Iris.time_third_party_cartopy                                                   |
|          | 5.05±0.01ms          | 5.02±0.02ms         |    0.99 | import_iris.Iris.time_third_party_cf_units                                                  |
|          | 121±0.7μs            | 123±0.7μs           |    1.01 | import_iris.Iris.time_third_party_cftime                                                    |
|          | 2.53±0.01ms          | 2.54±0.02ms         |    1.01 | import_iris.Iris.time_third_party_matplotlib                                                |
|          | 526±20μs             | 521±9μs             |    0.99 | import_iris.Iris.time_third_party_numpy                                                     |
|          | 173±1μs              | 172±1μs             |    0.99 | import_iris.Iris.time_third_party_scipy                                                     |
|          | 98.9±0.7μs           | 101±1μs             |    1.02 | import_iris.Iris.time_time                                                                  |
|          | 847±4μs              | 849±10μs            |    1    | import_iris.Iris.time_util                                                                  |
|          | 64.3±7μs             | 63.1±1μs            |    0.98 | iterate.IZip.time_izip                                                                      |
|          | 9.84±0.08ms          | 10.0±0.1ms          |    1.02 | load.LoadAndRealise.time_load((1280, 960, 5), False, 'FF')                                  |
|          | 15.1±0.4ms           | 15.6±0.4ms          |    1.03 | load.LoadAndRealise.time_load((1280, 960, 5), False, 'NetCDF')                              |
|          | 9.68±0.04ms          | 9.78±0.1ms          |    1.01 | load.LoadAndRealise.time_load((1280, 960, 5), False, 'PP')                                  |
|          | 17.8±0.1ms           | 18.6±0.4ms          |    1.05 | load.LoadAndRealise.time_load((1280, 960, 5), False, 'Zarr')                                |
|          | 9.78±0.05ms          | 9.88±0.1ms          |    1.01 | load.LoadAndRealise.time_load((1280, 960, 5), True, 'FF')                                   |
|          | 12.3±0.09ms          | 12.4±0.2ms          |    1.01 | load.LoadAndRealise.time_load((1280, 960, 5), True, 'NetCDF')                               |
|          | 9.78±0.02ms          | 9.79±0.1ms          |    1    | load.LoadAndRealise.time_load((1280, 960, 5), True, 'PP')                                   |
|          | 18.0±0.2ms           | 18.4±0.4ms          |    1.02 | load.LoadAndRealise.time_load((1280, 960, 5), True, 'Zarr')                                 |
|          | 1.48±0.01s           | 1.50±0s             |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'FF')                                    |
|          | 11.3±0.08ms          | 11.3±0.4ms          |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'NetCDF')                                |
|          | 1.49±0s              | 1.50±0.01s          |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'PP')                                    |
|          | 16.4±0.2ms           | 16.8±0.2ms          |    1.02 | load.LoadAndRealise.time_load((2, 2, 1000), False, 'Zarr')                                  |
|          | 1.48±0.01s           | 1.50±0.01s          |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), True, 'FF')                                     |
|          | 11.2±0.04ms          | 11.4±0.1ms          |    1.01 | load.LoadAndRealise.time_load((2, 2, 1000), True, 'NetCDF')                                 |
|          | 1.49±0.01s           | 1.47±0.03s          |    0.99 | load.LoadAndRealise.time_load((2, 2, 1000), True, 'PP')                                     |
|          | 16.8±0.1ms           | 16.7±0.3ms          |    1    | load.LoadAndRealise.time_load((2, 2, 1000), True, 'Zarr')                                   |
|          | 5.21±0.07ms          | 5.28±0.05ms         |    1.01 | load.LoadAndRealise.time_load((50, 50, 2), False, 'FF')                                     |
|          | 11.0±0.09ms          | 11.0±0.2ms          |    1    | load.LoadAndRealise.time_load((50, 50, 2), False, 'NetCDF')                                 |
|          | 5.01±0.05ms          | 5.08±0.04ms         |    1.01 | load.LoadAndRealise.time_load((50, 50, 2), False, 'PP')                                     |
|          | 17.8±0.2ms           | 18.0±0.2ms          |    1.01 | load.LoadAndRealise.time_load((50, 50, 2), False, 'Zarr')                                   |
|          | 5.22±0.03ms          | 5.25±0.05ms         |    1.01 | load.LoadAndRealise.time_load((50, 50, 2), True, 'FF')                                      |
|          | 11.0±0.1ms           | 11.2±0.2ms          |    1.02 | load.LoadAndRealise.time_load((50, 50, 2), True, 'NetCDF')                                  |
|          | 5.08±0.03ms          | 5.13±0.1ms          |    1.01 | load.LoadAndRealise.time_load((50, 50, 2), True, 'PP')                                      |
|          | 18.1±0.2ms           | 18.4±0.2ms          |    1.02 | load.LoadAndRealise.time_load((50, 50, 2), True, 'Zarr')                                    |
|          | 22.6±0.6ms           | 23.1±1ms            |    1.02 | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'FF')                               |
|          | 21.8±0.5ms           | 21.9±0.6ms          |    1    | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'NetCDF')                           |
|          | 12.9±0.8ms           | 12.7±0.9ms          |    0.98 | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'PP')                               |
|          | 18.1±0.5ms           | 18.0±0.5ms          |    0.99 | load.LoadAndRealise.time_realise((1280, 960, 5), False, 'Zarr')                             |
|          | 28.2±2ms             | 28.8±2ms            |    1.02 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'FF')                                |
|          | 70.3±0.5ms           | 69.9±0.2ms          |    0.99 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'NetCDF')                            |
|          | 28.0±1ms             | 28.2±1ms            |    1.01 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'PP')                                |
|          | 16.8±0.7ms           | 17.0±0.8ms          |    1.01 | load.LoadAndRealise.time_realise((1280, 960, 5), True, 'Zarr')                              |
|          | 626±2ms              | 629±3ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'FF')                                 |
|          | 3.45±0.05ms          | 3.69±0.2ms          |    1.07 | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'NetCDF')                             |
|          | 628±2ms              | 626±2ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'PP')                                 |
|          | 246±1ms              | 249±2ms             |    1.01 | load.LoadAndRealise.time_realise((2, 2, 1000), False, 'Zarr')                               |
|          | 626±1ms              | 629±2ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'FF')                                  |
|          | 3.45±0.09ms          | 3.55±0.1ms          |    1.03 | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'NetCDF')                              |
|          | 628±3ms              | 626±6ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'PP')                                  |
|          | 385±2ms              | 384±3ms             |    1    | load.LoadAndRealise.time_realise((2, 2, 1000), True, 'Zarr')                                |
|          | 2.19±0.05ms          | 2.22±0.06ms         |    1.01 | load.LoadAndRealise.time_realise((50, 50, 2), False, 'FF')                                  |
|          | 3.44±0.1ms           | 3.52±0.2ms          |    1.02 | load.LoadAndRealise.time_realise((50, 50, 2), False, 'NetCDF')                              |
|          | 2.19±0.03ms          | 2.18±0.08ms         |    1    | load.LoadAndRealise.time_realise((50, 50, 2), False, 'PP')                                  |
|          | 2.02±0.07ms          | 2.23±0.1ms          |    1.1  | load.LoadAndRealise.time_realise((50, 50, 2), False, 'Zarr')                                |
|          | 2.16±0.06ms          | 2.22±0.06ms         |    1.03 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'FF')                                   |
|          | 3.46±0.09ms          | 3.58±0.2ms          |    1.04 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'NetCDF')                               |
|          | 2.19±0.06ms          | 2.25±0.04ms         |    1.03 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'PP')                                   |
|          | 2.43±0.08ms          | 2.53±0.1ms          |    1.04 | load.LoadAndRealise.time_realise((50, 50, 2), True, 'Zarr')                                 |
|          | 342±1ms              | 345±2ms             |    1.01 | load.ManyCubes.time_many_cube_load                                                          |
|          | 81.9±0.4ms           | 82.2±0.7ms          |    1    | load.ManyVars.time_many_var_load                                                            |
|          | 10.1±0.09ms          | 9.93±0.08ms         |    0.98 | load.STASHConstraint.time_stash_constraint((1280, 960, 5), 'FF')                            |
|          | 9.84±0.08ms          | 9.89±0.07ms         |    1    | load.STASHConstraint.time_stash_constraint((1280, 960, 5), 'PP')                            |
|          | 1.51±0.01s           | 1.50±0.01s          |    1    | load.STASHConstraint.time_stash_constraint((2, 2, 1000), 'FF')                              |
|          | 1.49±0s              | 1.48±0.01s          |    0.99 | load.STASHConstraint.time_stash_constraint((2, 2, 1000), 'PP')                              |
|          | 5.31±0.07ms          | 5.28±0.01ms         |    0.99 | load.STASHConstraint.time_stash_constraint((2, 2, 2), 'FF')                                 |
|          | 5.13±0.04ms          | 5.08±0.03ms         |    0.99 | load.STASHConstraint.time_stash_constraint((2, 2, 2), 'PP')                                 |
|          | 8.96±0.08ms          | 8.95±0.07ms         |    1    | load.StructuredFF.time_structured_load((1280, 960, 5), False)                               |
|          | 5.53±0.03ms          | 5.53±0.03ms         |    1    | load.StructuredFF.time_structured_load((1280, 960, 5), True)                                |
|          | 1.48±0.01s           | 1.46±0.01s          |    0.99 | load.StructuredFF.time_structured_load((2, 2, 1000), False)                                 |
|          | 430±3ms              | 425±3ms             |    0.99 | load.StructuredFF.time_structured_load((2, 2, 1000), True)                                  |
|          | 4.35±0.05ms          | 4.36±0.03ms         |    1    | load.StructuredFF.time_structured_load((2, 2, 2), False)                                    |
|          | 4.22±0.2ms           | 4.19±0.04ms         |    0.99 | load.StructuredFF.time_structured_load((2, 2, 2), True)                                     |
|          | 154±2ms              | 153±1ms             |    0.99 | load.TimeConstraint.time_time_constraint(20, 'FF')                                          |
|          | 13.8±0.1ms           | 13.8±0.08ms         |    1    | load.TimeConstraint.time_time_constraint(20, 'NetCDF')                                      |
|          | 154±0.8ms            | 151±3ms             |    0.98 | load.TimeConstraint.time_time_constraint(20, 'PP')                                          |
|          | 20.8±0.3ms           | 20.4±0.2ms          |    0.98 | load.TimeConstraint.time_time_constraint(20, 'Zarr')                                        |
|          | 30.6±0.3ms           | 30.9±0.1ms          |    1.01 | load.TimeConstraint.time_time_constraint(3, 'FF')                                           |
|          | 13.5±0.1ms           | 13.4±0.1ms          |    1    | load.TimeConstraint.time_time_constraint(3, 'NetCDF')                                       |
|          | 30.4±0.1ms           | 30.7±0.2ms          |    1.01 | load.TimeConstraint.time_time_constraint(3, 'PP')                                           |
|          | 20.3±0.3ms           | 20.4±0.4ms          |    1    | load.TimeConstraint.time_time_constraint(3, 'Zarr')                                         |
|          | 17.7±0.6ms           | 17.5±0.5ms          |    0.99 | load.ugrid.BasicLoading.time_load_file(1)                                                   |
|          | 46.6±0.8ms           | 48.9±2ms            |    1.05 | load.ugrid.BasicLoading.time_load_file(200000)                                              |
|          | 7.56±0.2ms           | 7.61±0.3ms          |    1.01 | load.ugrid.BasicLoading.time_load_mesh(1)                                                   |
|          | 14.8±0.4ms           | 16.8±0.9ms          |    1.13 | load.ugrid.BasicLoading.time_load_mesh(200000)                                              |
|          | 17.5±0.5ms           | 17.2±0.2ms          |    0.99 | load.ugrid.BasicLoadingTime.time_load_file(1)                                               |
|          | 17.8±0.3ms           | 17.8±0.4ms          |    1    | load.ugrid.BasicLoadingTime.time_load_file(200000)                                          |
|          | 7.36±0.1ms           | 7.51±0.1ms          |    1.02 | load.ugrid.BasicLoadingTime.time_load_mesh(1)                                               |
|          | 10.4±0.3ms           | 10.7±0.3ms          |    1.03 | load.ugrid.BasicLoadingTime.time_load_mesh(200000)                                          |
|          | 19.5±0.4ms           | 19.8±0.5ms          |    1.02 | load.ugrid.Callback.time_load_file_callback(1)                                              |
|          | 59.3±2ms             | 59.5±2ms            |    1    | load.ugrid.Callback.time_load_file_callback(200000)                                         |
|          | 19.2±0.3ms           | 20.2±0.4ms          |    1.05 | load.ugrid.CallbackTime.time_load_file_callback(1)                                          |
|          | 22.2±0.3ms           | 21.4±0.7ms          |    0.97 | load.ugrid.CallbackTime.time_load_file_callback(200000)                                     |
|          | 3.44±0.1ms           | 3.70±0.3ms          |    1.07 | load.ugrid.DataRealisation.time_realise_data(10000)                                         |
|          | 4.62±0.2ms           | 4.62±0.3ms          |    1    | load.ugrid.DataRealisation.time_realise_data(200000)                                        |
|          | 46.2±2ms             | 48.3±3ms            |    1.04 | load.ugrid.DataRealisationTime.time_realise_data(10000)                                     |
|          | 1.02±0.03s           | 1.06±0.05s          |    1.04 | load.ugrid.DataRealisationTime.time_realise_data(200000)                                    |
|          | 1.08±0.04s           | 1.10±0.03s          |    1.02 | merge_concat.Concatenate.time_concatenate(False)                                            |
|          | 443±5ms              | 448±9ms             |    1.01 | merge_concat.Concatenate.time_concatenate(True)                                             |
|          | 2.21±0G              | 2.21±0G             |    1    | merge_concat.Concatenate.tracemalloc_concatenate(False)                                     |
|          | 71.7±2M              | 71.9±2M             |    1    | merge_concat.Concatenate.tracemalloc_concatenate(True)                                      |
|          | 32.6±1ms             | 35.8±2ms            |    1.1  | merge_concat.Merge.time_merge                                                               |
|          | 126±0.03M            | 126±0.03M           |    1    | merge_concat.Merge.tracemalloc_merge                                                        |
|          | 5.57±0.03ms          | 5.64±0.1ms          |    1.01 | mesh.utils.regions_combine.CombineRegionsComputeRealData.time_compute_data(50)              |
|          | 145±0.9ms            | 146±1ms             |    1.01 | mesh.utils.regions_combine.CombineRegionsComputeRealData.time_compute_data(500)             |
|          | 768±1k               | 767±1k              |    1    | mesh.utils.regions_combine.CombineRegionsComputeRealData.tracemalloc_compute_data(50)       |
|          | 60.2±0M              | 60.2±0M             |    1    | mesh.utils.regions_combine.CombineRegionsComputeRealData.tracemalloc_compute_data(500)      |
|          | 18.7±0.2ms           | 18.7±0.3ms          |    1    | mesh.utils.regions_combine.CombineRegionsCreateCube.time_create_combined_cube(50)           |
|          | 22.0±0.3ms           | 21.8±0.5ms          |    0.99 | mesh.utils.regions_combine.CombineRegionsCreateCube.time_create_combined_cube(500)          |
|          | 1.23±0M              | 1.23±0M             |    1    | mesh.utils.regions_combine.CombineRegionsCreateCube.tracemalloc_create_combined_cube(50)    |
|          | 25±0M                | 25±0M               |    1    | mesh.utils.regions_combine.CombineRegionsCreateCube.tracemalloc_create_combined_cube(500)   |
|          | 112±3ms              | 110±2ms             |    0.98 | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.time_stream_file2file(50)         |
|          | 405±6ms              | 403±7ms             |    0.99 | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.time_stream_file2file(500)        |
|          | 1.51±0.03M           | 1.51±0.03M          |    1    | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.tracemalloc_stream_file2file(50)  |
|          | 96.5±0.03M           | 96.6±0.01M          |    1    | mesh.utils.regions_combine.CombineRegionsFileStreamedCalc.tracemalloc_stream_file2file(500) |
|          | 73.2±0.7ms           | 74.3±1ms            |    1.02 | mesh.utils.regions_combine.CombineRegionsSaveData.time_save(50)                             |
|          | 356±4ms              | 361±6ms             |    1.01 | mesh.utils.regions_combine.CombineRegionsSaveData.time_save(500)                            |
|          | 1.37±0.05M           | 1.41±0.04M          |    1.03 | mesh.utils.regions_combine.CombineRegionsSaveData.tracemalloc_save(50)                      |
|          | 96.4±0.06M           | 96.4±0.05M          |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.tracemalloc_save(500)                     |
|          | 2.175361             | 2.175361            |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.track_filesize_saved(50)                  |
|          | 216.01536099999998   | 216.01536099999998  |    1    | mesh.utils.regions_combine.CombineRegionsSaveData.track_filesize_saved(500)                 |
|          | 6.34±0.06ms          | 6.34±0.05ms         |    1    | plot.AuxSort.time_aux_sort                                                                  |
|          | 54.3±1ms             | 56.9±2ms            |    1.05 | regridding.CurvilinearRegridding.time_regrid_pic                                            |
|          | 136±3M               | 136±3M              |    1    | regridding.CurvilinearRegridding.tracemalloc_regrid_pic                                     |
|          | 96.9±5ms             | 96.9±6ms            |    1    | regridding.HorizontalChunkedRegridding.time_regrid_area_w                                   |
|          | 56.2±1ms             | 56.2±0.9ms          |    1    | regridding.HorizontalChunkedRegridding.time_regrid_area_w_new_grid                          |
|          | 107±0.1M             | 107±0.1M            |    1    | regridding.HorizontalChunkedRegridding.tracemalloc_regrid_area_w                            |
|          | 147±0.03M            | 147±0.03M           |    1    | regridding.HorizontalChunkedRegridding.tracemalloc_regrid_area_w_new_grid                   |
|          | 4.81±0.08ms          | 4.81±0.2ms          |    1    | save.Save.time_save_cube(50, False, 'NetCDF')                                               |
|          | 23.1±0.5ms           | 23.9±1ms            |    1.03 | save.Save.time_save_cube(50, False, 'Zarr')                                                 |
|          | 79.7±2ms             | 79.8±1ms            |    1    | save.Save.time_save_cube(50, True, 'NetCDF')                                                |
|          | 170±5ms              | 165±3ms             |    0.98 | save.Save.time_save_cube(50, True, 'Zarr')                                                  |
|          | 20.9±0.7ms           | 21.2±0.5ms          |    1.01 | save.Save.time_save_cube(600, False, 'NetCDF')                                              |
|          | 93.9±2ms             | 93.5±2ms            |    1    | save.Save.time_save_cube(600, False, 'Zarr')                                                |
|          | 290±10ms             | 292±3ms             |    1.01 | save.Save.time_save_cube(600, True, 'NetCDF')                                               |
|          | 890±10ms             | 880±6ms             |    0.99 | save.Save.time_save_cube(600, True, 'Zarr')                                                 |
|          | 1.38±0.2μs           | 1.21±0.1μs          |    0.88 | save.Save.time_save_mesh(50, False, 'NetCDF')                                               |
|          | 1.17±0.08μs          | 1.40±0.3μs          |    1.2  | save.Save.time_save_mesh(50, False, 'Zarr')                                                 |
|          | 60.5±1ms             | 61.3±1ms            |    1.01 | save.Save.time_save_mesh(50, True, 'NetCDF')                                                |
|          | 2.30±0.3μs           | 2.36±0.2μs          |    1.03 | save.Save.time_save_mesh(50, True, 'Zarr')                                                  |
|          | 2.68±0.2μs           | 2.47±0.2μs          |    0.92 | save.Save.time_save_mesh(600, False, 'NetCDF')                                              |
|          | 2.65±0.1μs           | 2.76±0.2μs          |    1.04 | save.Save.time_save_mesh(600, False, 'Zarr')                                                |
|          | 249±4ms              | 252±8ms             |    1.01 | save.Save.time_save_mesh(600, True, 'NetCDF')                                               |
|          | 2.95±0.2μs           | 2.68±0.1μs          |    0.91 | save.Save.time_save_mesh(600, True, 'Zarr')                                                 |
|          | 33.8±1k              | 33.8±1k             |    1    | save.Save.tracemalloc_save(50, False, 'NetCDF')                                             |
|          | 313±4k               | 314±3k              |    1    | save.Save.tracemalloc_save(50, False, 'Zarr')                                               |
|          | 1.91±0.2M            | 1.91±0.09M          |    1    | save.Save.tracemalloc_save(50, True, 'NetCDF')                                              |
|          | 1.4±0.2M             | 1.31±0.2M           |    0.93 | save.Save.tracemalloc_save(50, True, 'Zarr')                                                |
|          | 33.9±1k              | 33.9±1k             |    1    | save.Save.tracemalloc_save(600, False, 'NetCDF')                                            |
|          | 4.12±0.2M            | 4.22±0.2M           |    1.03 | save.Save.tracemalloc_save(600, False, 'Zarr')                                              |
|          | 190±20M              | 225±10M             |    1.18 | save.Save.tracemalloc_save(600, True, 'NetCDF')                                             |
|          | 261±10M              | 252±20M             |    0.96 | save.Save.tracemalloc_save(600, True, 'Zarr')                                               |
|          | 41.3±0.7ms           | 40.8±0.6ms          |    0.99 | stats.PearsonR.time_lazy                                                                    |
|          | 9.80±0.2ms           | 9.93±0.2ms          |    1.01 | stats.PearsonR.time_real                                                                    |
|          | 29±1M                | 29±0.8M             |    1    | stats.PearsonR.tracemalloc_lazy                                                             |
|          | 18.3±0M              | 18.3±0M             |    1    | stats.PearsonR.tracemalloc_real                                                             |
|          | 24.0±0.4ms           | 24.1±0.5ms          |    1.01 | trajectory.TrajectoryInterpolation.time_trajectory_linear                                   |
|          | 81.0±0.6ms           | 80.9±0.5ms          |    1    | trajectory.TrajectoryInterpolation.time_trajectory_nearest                                  |
|          | 17.6±0.01M           | 17.6±0.01M          |    1    | trajectory.TrajectoryInterpolation.tracemalloc_trajectory_linear                            |
|          | 7.74±0.01M           | 7.74±0.01M          |    1    | trajectory.TrajectoryInterpolation.tracemalloc_trajectory_nearest                           |

Generated by GHA run 40505949895

@pp-mo pp-mo left a comment

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.

👍 confirmed changes all equivalent to those in https://github.com/trexfeathers/iris/pull/101/changes

@pp-mo
pp-mo merged commit c9e1b53 into SciTools:brownfield Oct 27, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Agentic benchmark_this Request that this pull request be benchmarked to check if it introduces performance shifts Type: Feature Branch Highlight this for a feature branch

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants