perf: cache default ArraySpec for regular chunk grids#3908
Conversation
For regular grids, all chunks have the same codec_shape, so we can build the ArraySpec once and reuse it for every chunk — avoiding the per-chunk ChunkGrid.__getitem__ + ArraySpec construction overhead. Adds _get_default_chunk_spec() and uses it in _get_selection and _set_selection. Saves ~5ms per 1000 chunks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3908 +/- ##
=======================================
Coverage 93.32% 93.32%
=======================================
Files 88 88
Lines 11827 11833 +6
=======================================
+ Hits 11037 11043 +6
Misses 790 790
🚀 New features to boost your workflow:
|
Merging this PR will improve performance by 11.1%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | test_slice_indexing[None-(slice(None, None, None), slice(None, None, None), slice(None, None, None))-memory] |
389.8 ms | 352.5 ms | +10.59% |
| ⚡ | WallTime | test_slice_indexing[None-(slice(0, None, 4), slice(0, None, 4), slice(0, None, 4))-memory] |
386.7 ms | 348.3 ms | +11.01% |
| ⚡ | WallTime | test_slice_indexing[None-(slice(10, -10, 4), slice(10, -10, 4), slice(10, -10, 4))-memory] |
211.6 ms | 190.4 ms | +11.1% |
| ⚡ | WallTime | test_slice_indexing[None-(slice(None, None, None), slice(0, 3, 2), slice(0, 10, None))-memory_get_latency] |
4.3 ms | 3.9 ms | +10.54% |
Comparing d-v-b:perf/cache-default-chunk-spec (6fa93cb) with main (029c376)2
Footnotes
-
6 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
-
No successful run was found on
main(c4730be) during the generation of this report, so 029c376 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩
Pulls in the upstream-main work that landed on the remote branch after the previous local merge: PR zarr-developers#3975 (refactor _ShardIndex to store chunks_per_shard explicitly), PR zarr-developers#3908 (cache default ArraySpec), zarr-developers#3935 (cd workflow), zarr-developers#3978 (zarr-metadata constants), zarr-developers#3979 (drop fixed-length utf32 warning). Conflicts resolved: - src/zarr/codecs/sharding.py imports: drop the now-unused `from operator import itemgetter` per zarr-developers#3975, keep our `ClassVar, Final, Literal` additions for the enum-deprecation types. - tests/test_codecs/test_sharding.py imports: combine `from zarr.core.metadata.v3 import ArrayV3Metadata` (ours, for the dict-shards coverage test) with `from zarr.core.indexing import c_order_iter` (theirs, for the new vectorized-slice tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
For regular grids, all chunks have the same codec_shape, so we can
build the ArraySpec once and reuse it for every chunk — avoiding the
per-chunk ChunkGrid.getitem + ArraySpec construction overhead.
Adds _get_default_chunk_spec() and uses it in _get_selection and
_set_selection. Saves ~5ms per 1000 chunks.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com