Skip to content

benchmarks: narrow a store worth narrowing, and report sizes - #44

Merged
Claptar merged 1 commit into
mainfrom
bench/recast-sizes
Oct 15, 2026
Merged

Claptar merged 1 commit into
mainfrom
bench/recast-sizes

Conversation

@Claptar

@Claptar Claptar commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

The recast benchmark measured nothing. convert-dtype cast the main fixture to float32, but the fixture was already float32 with int32 indices, so 291 MB went in and 291 MB came out.

What changed

  • recast-narrow (headline) replaces convert-dtype. It starts from a copy of the main input with X stored as float64 values and int64 indices/indptr, and narrows it to float32/int32. That's the situation issue Feature request. Change dtype of X #13 describes.
  • recast-narrow-lzf: the same narrowing on an lzf-compressed X (see below for why there are two).
  • Before → after sizes. The recast cases now report size as input → output (±%). That includes convert-layout, where 0.7.0 fixed a --layout that tripled the file.
  • Fair baseline. In the uncompressed case the anndata baseline also writes uncompressed, so it isn't credited with a saving that lzf made rather than the cast.
  • New names. The old case name is retired, so "vs previous" doesn't compare against 0.7.0's no-op numbers.

Why two variants

Whether narrowing saves disk space depends on compression. Integer counts stored as float64 are mostly zero bytes, which a compressor strips anyway. On a 20M-nonzero matrix:

X stored as float64/int64 float32/int32
uncompressed 320 MB 160 MB
lzf 115 MB 110 MB
gzip 51 MB 53 MB

Uncompressed is write_h5ad's default, so it's the headline case. The lzf case keeps the small saving visible. On a compressed store, narrowing pays off in memory once the matrix is loaded, not on disk.

Local ci-tier run (50,000 × 20,000, warm cache, one repeat)

Case adata-cli anndata (in memory) Input → output
recast-narrow 0.72 s, 129 MB 1.55 s, 1.7 GB 815.6 MB → 415.4 MB (−49%)
recast-narrow-lzf 1.64 s, 133 MB 2.22 s, 1.8 GB 302.5 MB → 291.1 MB (−4%)
convert-layout (streaming) 8.18 s, 404 MB 2.06 s, 1.0 GB 291.2 MB → 297.0 MB (+2%)

Two new harness tests cover this: one checks that the wide fixtures hold the same matrix in wider dtypes, and one checks the size column's rendering.

🤖 Generated with Claude Code

The dtype case cast the main fixture to float32, which it already was,
so it measured a rewrite that changed nothing: 291 MB in, 291 MB out.

recast-narrow now starts from a copy of the main input with X stored as
float64 values and int64 indices, narrows it to float32/int32, and its
table reads input -> output with the change; convert-layout reports the
same, since 0.7.0 fixed a --layout that tripled the file.

Two wide variants, because compression decides the answer: integer
counts in float64 are mostly zero bytes, so narrowing an uncompressed X
halves the file while an lzf one shrinks by a few percent. recast-narrow
uses the uncompressed one (write_h5ad's default), recast-narrow-lzf the
other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 15, 2026 14:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T14:08:33.836491Z 23522bc PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 23522bc591

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread benchmarks/cases.py
"X.indices = X.indices.astype('int32')\n"
"X.indptr = X.indptr.astype('int32')\n"
"obj.X = X\n"
"obj.write_h5ad(OUT, compression=None)\n"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve compression for non-X elements in the baseline

In the recast-narrow case, the wide fixture has only X made uncompressed; _widen copies obs, var, obsm, and other elements from the original lzf-compressed fixture unchanged. The CLI likewise preserves those elements' compression, but write_h5ad(..., compression=None) rewrites the entire baseline output without compression. Consequently, the reported runtime and input-to-output size compare an X recast plus unrelated decompression against a pure recast. Preserve the non-X datasets' filters in the baseline, or make the whole input uncompressed for both contenders.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (py3.13)

1 283 tests  +2   1 283 ✅ +2   5m 6s ⏱️ -3s
    1 suites ±0       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 23522bc. ± Comparison against base commit 63d1aae.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (py3.12)

1 283 tests  +2   1 283 ✅ +2   5m 20s ⏱️ + 2m 42s
    1 suites ±0       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 23522bc. ± Comparison against base commit 63d1aae.

@Claptar
Claptar merged commit 661c153 into main Oct 15, 2026
6 checks passed
@Claptar
Claptar deleted the bench/recast-sizes branch October 15, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants