Skip to content

Expose the remote HDF5 knobs and announce the gc pause - #879

Merged
d-chambers merged 3 commits into
devfrom
remote-io-knobs
Aug 12, 2026
Merged

Expose the remote HDF5 knobs and announce the gc pause#879
d-chambers merged 3 commits into
devfrom
remote-io-knobs

Conversation

@d-chambers

@d-chambers d-chambers commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Description

Follow-up to #784, which is now merged, so this sits directly on dev.

#784 introduced two remote-IO behaviours that a user cannot see or influence:

  • The HTTP block cache is capped at a hard-coded 8 blocks, sitting directly next to remote_hdf5_block_size, which is configurable. Their product is what an open remote HDF5 handle retains — ~40 MiB by default — so the one number that sets memory use was the one you could not change.
  • Reading remote HDF5 pauses automatic garbage collection process-wide. It is correct, it is h5py's recommended mitigation, and it leaves no trace. A program whose memory grows, or which finds gc.isenabled() returning False, has nothing connecting either to a remote read.

This adds the missing surface, using the existing configuration machinery rather than a new idiom.

remote_hdf5_max_blocks

Blocks one open HTTP HDF5 handle may keep cached; default 8, unchanged from #784. H5Reader._get_open_kwargs now reads it instead of hard-coding the value.

warn_on_gc_pause

Warned once per process, the first time a pause is taken, mirroring the existing warn_on_remote_cache. A spool over thousands of remote files says it once. Set warn_on_gc_pause=False to silence it.

The warning explains what is paused, why, and that reference counting is unaffected — the three things someone diagnosing memory growth needs.

Documentation

The remote-patches tutorial gains a Tuning Remote HDF5 Transfers section. Rather than just listing the knobs, it gives direction for the two workloads, which pull opposite ways:

  • Scanning many files reads kilobytes from two distant regions per file and then closes it. Large blocks spend megabytes to deliver kilobytes and the cache is never reused, so shrink both (~1 MiB retained per handle instead of 40 MiB). With the caveat that each block is a request, so on a high-latency link over-shrinking costs more in round trips than it saves in bytes.
  • Reading whole patches pulls large contiguous ranges, and BlockCache issues one request per block (verified in fsspec/caching.py: intermediate blocks are fetched individually, with a source comment noting they cannot be coalesced without breaking the LRU). So bigger blocks cut request count, and the LRU earns little on a streaming read — trade blocks for size. It also points out that if you are reading whole files, letting DASCore materialize them locally beats any streaming pattern.
  • Many handles at once multiplies the figure, since it is per open handle; lower max_blocks first, because evictions cost nothing for scans and sequential reads.

The GC section now mentions the warning and how to turn it off. The configuration page's pointer to remote-IO settings lists the three new names.

Notes

The pause itself stays automatic. It is a correctness requirement rather than a preference — reading remote HDF5 without it deadlocks — so making it opt-in would make the default path the broken one. What is configurable here is the visibility of the pause and the memory of the cache, which are the parts a user might legitimately want to change.

There is no test that the fields are settable; that exercises pydantic and the config machinery rather than DASCore. The behaviour is covered: the warning fires once, can be silenced, and silencing it does not disable the pause. remote_hdf5_max_blocks is covered through test_remote_h5_open_kwargs_are_tuned.

Changelog

  • added: remote_hdf5_max_blocks config option caps the blocks an open remote HDF5 handle caches over HTTP. Together with remote_hdf5_block_size it sets the memory one handle retains (~40 MB by default).
  • added: warn_on_gc_pause config option; DASCore now warns once per process when a remote HDF5 read pauses automatic garbage collection. Set it to False to silence.

Checklist

I have:

  • filled in the Changelog section above (see docs/contributing/general_guidelines.qmd).

I have (if applicable):

  • referenced the GitHub issue this PR closes.
  • documented the new feature with docstrings and/or appropriate doc page.
  • included tests. See testing guidelines.
  • added the "ready_for_review" tag once the PR is ready to be reviewed.

Summary by CodeRabbit

  • New Features

    • Added configurable limits for cached blocks during remote HDF5 reads.
    • Added an option to control warnings when automatic garbage collection is paused.
    • Remote HDF5 operations now provide a one-time warning about paused garbage collection, with support for suppressing it.
    • Remote HDF5 block-size settings now require positive values for reliable streaming.
  • Documentation

    • Expanded configuration and remote I/O guidance with cache-tuning settings, warning controls, suppression options, and usage examples.

The HTTP block cap was hard-coded next to a configurable block size, and
pausing collection process-wide left no trace a user could connect to a
remote read.

- Add remote_hdf5_max_blocks; _get_open_kwargs reads it.
- Add warn_on_gc_pause, warned once per process when the pause is taken.
- Document both, plus the memory they imply, in the remote-patches
  tutorial and the configuration page.
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e39f0213-318a-4c1d-89ca-d4751de9ef54

📥 Commits

Reviewing files that changed from the base of the PR and between 3b1f8dc and e361f70.

📒 Files selected for processing (6)
  • dascore/config.py
  • dascore/io/core.py
  • dascore/utils/hdf5.py
  • dascore/utils/remote_io.py
  • docs/tutorial/remote_patches.qmd
  • tests/test_utils/test_gc_pause.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • dascore/utils/hdf5.py
  • dascore/config.py
  • docs/tutorial/remote_patches.qmd

📝 Walkthrough

Walkthrough

Changes

Remote HDF5 settings now control block-cache capacity and garbage-collection pause warnings. HTTP HDF5 handles use the configured block limit. Format probing suppresses these warnings. Documentation and tests cover configuration, suppression, fork behavior, and warning errors.

Remote HDF5 controls

Layer / File(s) Summary
Remote HDF5 cache controls
dascore/config.py, dascore/utils/hdf5.py, docs/tutorial/configuration.qmd, docs/tutorial/remote_patches.qmd
DascoreConfig validates remote_hdf5_block_size and adds remote_hdf5_max_blocks. HTTP HDF5 handles use the configured block limit. Documentation covers cache sizing, block fetching, and remote access patterns.
Garbage-collection pause warning
dascore/config.py, dascore/utils/remote_io.py, dascore/io/core.py, tests/test_utils/test_gc_pause.py, docs/tutorial/remote_patches.qmd
pause_gc emits one configurable UserWarning and supports suppression. Fork handling resets warning state. Format probing suppresses warnings. Tests cover warning errors, suppression, fork behavior, and pause accounting.

Possibly related PRs

  • DASDAE/dascore#784: Both changes modify remote HDF5 caching and garbage-collection pause behavior.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main changes: configurable remote HDF5 settings and a garbage-collection pause warning.
Description check ✅ Passed The description explains the problem, implementation, documentation, tests, changelog, and checklist status in sufficient detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch remote-io-knobs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@d-chambers d-chambers added ready_for_review PR is ready for review documentation Improvements or additions to documentation IO Work for reading/writing different formats labels Aug 12, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dascore/utils/remote_io.py`:
- Line 45: Update _reset_gc_pause_state() to reset the module-level
_gc_pause_warned flag to its initial false state after a fork. Add a fork-state
test verifying that a child process has warning state cleared and can emit its
once-per-process warning.
- Around line 60-63: Synchronize the check-and-set of _gc_pause_warned in the
relevant warning function using _gc_pause_lock so only one concurrent caller
claims the warning; keep warnings.warn outside the lock. Add a concurrency test
verifying the warning is emitted at most once per process.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e7778971-f353-417b-9a74-05f4ce845824

📥 Commits

Reviewing files that changed from the base of the PR and between 91db43f and 3b1f8dc.

📒 Files selected for processing (6)
  • dascore/config.py
  • dascore/utils/hdf5.py
  • dascore/utils/remote_io.py
  • docs/tutorial/configuration.qmd
  • docs/tutorial/remote_patches.qmd
  • tests/test_utils/test_gc_pause.py

Comment thread dascore/utils/remote_io.py
Comment thread dascore/utils/remote_io.py Outdated

@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: 3b1f8dcd27

ℹ️ 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 dascore/utils/remote_io.py
Comment thread dascore/utils/remote_io.py
Comment thread dascore/utils/hdf5.py Outdated
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (91db43f) to head (e361f70).

Additional details and impacted files
@@            Coverage Diff            @@
##               dev      #879   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          177       177           
  Lines        20615     20638   +23     
=========================================
+ Hits         20615     20638   +23     
Flag Coverage Δ
network 46.53% <96.29%> (+0.05%) ⬆️
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

- Warn after the pause is accounted for. A filter turning the warning into
  an error previously raised before the depth moved, and the caller's
  resume then released a pause it never took, freeing a live handle's.
- Claim the warned flag under the lock so two openers cannot both warn.
- Rearm the flag after a fork; a pool worker should announce its own pause.
- Read both HDF5 cache knobs from one config snapshot.
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

✅ Documentation built:
👉 Download
Note: You must be logged in to github and a DASDAE member to access the link.

- Do not announce the gc pause while probing formats. The warning claimed
  an HDF5 read before h5py had decided the resource was one, and under
  warnings-as-errors it landed in _get_format's robustness handler and read
  as 'wrong format' -- silently skipping the reader which did match.
- Validate remote_hdf5_block_size as positive; zero made fsspec stream the
  whole file, the opposite of what the docs now advise.
- Fix the scanning recipe, which told users to spool a remote directory;
  that raises InvalidSpoolError.
- Fork for real in the fork test rather than calling the reset hook, and
  bound it since the repo sets no global timeout. Drop the unfailable
  silencing test. Trim repeated prose.
@d-chambers
d-chambers merged commit 617b6a2 into dev Aug 12, 2026
31 checks passed
@d-chambers
d-chambers deleted the remote-io-knobs branch August 12, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation IO Work for reading/writing different formats ready_for_review PR is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant