bench: add read benchmarks against zarr-python - #151
Open
kylebarron wants to merge 5 commits into
Open
Conversation
Adds bench/bench_read.py, which writes a fixture array with zarr-python and times full-array reads. This commit measures the stock zarr-python codec pipeline only; the zarrs and zarrista rows follow. Adds a bench dependency group and bench/* ruff ignores. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Runs the same read through the zarrs Rust codec pipeline plugin. This row separates the effect of Rust codecs from the effect of a native end-to-end binding, which the zarrista row measures next. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds --threads, which pins zarr-python's threading.max_workers and rayon's RAYON_NUM_THREADS to the same value for every implementation. Rayon reads RAYON_NUM_THREADS only when it first builds its global pool, so the script sets the variable before it imports zarrista or zarrs. Every extension import is therefore function-local. Replaces argparse with click. A shape is now one comma-separated value, such as --shards 512,512. A click.ParamType converts and validates it, so the benchmark code only ever sees a valid shape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Records how to build and run them, what each row measures, and real output at the default parameters. States the release-build requirement first, because a debug build makes every number meaningless. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds zarrs to uv.lock, so that the lockfile matches the bench group in pyproject.toml. click was already locked for the docs group. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Written by Claude:
Adds a
bench/directory with one script that answers a single question: is the native zarrs binding actually faster than zarr-python?What it does
bench/bench_read.pywrites one array with zarr-python, then reads the whole array repeatedly with three implementations reading those same bytes:zarr-pythonzarr-python+zarrszarrsRust codec pipeline pluginzarristaarray[...], then.to_numpy()The middle row is the point. Without it you cannot tell whether a speed increase comes from Rust codecs or from a native end-to-end binding.
--shardsselects the scenario: give it for a sharded array, omit it for a plain chunked one.Results
Apple M-series laptop, 10 threads, release build, 8.4 MB
uint16array.Sharded (
--shards 512,512):Plain chunked:
The two Rust rows are close on the sharded array, but zarrista is about twice as fast as the
zarrscodec pipeline on the plain chunked array.Notes on method
.to_numpy()is inside zarrista's timed region, since the other two rows already return a NumPy array.--threadspins zarr-python'sthreading.max_workersand rayon'sRAYON_NUM_THREADSto the same value. Rayon reads that variable only when it first builds its global pool, so the script sets it before importing zarrista orzarrs. Every extension import is therefore function-local.--release. A debug build makes the numbers meaningless, and Python cannot detect the build profile at run time.bench/README.mdstates this first, and the printed header repeats it.Not covered
In-memory store (
zarrista.MemoryStore()has no API to ingest external bytes, so the two libraries could not read one set of bytes), partial/strided reads, writes, and remote object stores.Starting point was @d-v-b's gist from zarr-developers/zarr-python#4064.
🤖 Generated with Claude Code