Repository navigation
Lazy remote reads (S3) through a byte-range reader - #135
Merged
Merged
Conversation
jeandet
force-pushed
the
feat/remote-reads
branch
from
November 2, 2026 15:05
7a4fa3f to
de783e1
Compare
| // loading thread may need it, to fetch remote bytes through a Python reader. Each shared | ||
| // library linking CDFpp has its own copy: install it in the one that holds the lock. | ||
| inline std::atomic<void (*)(std::unique_lock<std::mutex>&)> wait_for_variable_lock | ||
| = +[](std::unique_lock<std::mutex>& lock) { lock.lock(); }; |
|
|
||
| inline void wait_for_variable_lock_without_gil(std::unique_lock<std::mutex>& lock) | ||
| { | ||
| without_gil([&] { lock.lock(); }); |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #135 +/- ##
==========================================
- Coverage 96.24% 96.22% -0.03%
==========================================
Files 91 94 +3
Lines 8824 9201 +377
==========================================
+ Hits 8493 8854 +361
- Misses 331 347 +16
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
cpp_utils gains byte-range readers, a reserved memory region and a lazy remote buffer (jeandet/cpp_utils#1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jeandet
force-pushed
the
feat/remote-reads
branch
from
November 2, 2026 16:01
d9b6857 to
420ab3b
Compare
cdf::io::load(reader) parses a file it reads through any byte-range reader (S3, HTTP...): only the records parsing needs are fetched, in batches, each byte at most once, into a cache in a reserved memory region. - Each record is ensured before it is parsed; VXR child headers and data blocks are fetched in one batch before decoding. - Decode threads never fetch. - Fetches read ahead 1 MiB by default; settings come from keywords, then CDFPP_REMOTE_* environment variables. - A hook lets bindings release their interpreter lock while waiting for a variable that another thread is loading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pycdfpp.load('s3://...') reads a file lazily through fsspec
(pip install pycdfpp[s3]). With no AWS credentials, s3:// reads
anonymously, so public buckets need no setup; storage_options replaces
that default. Any object with size() and read_ranges() works as a reader
for other sources.
- Waiting on a variable's lock releases the GIL: the loading thread may
need it to call the Python reader.
- Remote reads are compiled out of WASM builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jeandet
force-pushed
the
feat/remote-reads
branch
from
November 2, 2026 18:21
420ab3b to
b210f57
Compare
|
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.



Read CDF files straight from S3 (or any remote store)
On S3 you pay per byte and per request. This PR reads a remote CDF lazily: only the records you need, each fetched once.
How it works
pycdfpp.loada URL. It goes through fsspec, sos3://,gs://,az://andhttps://all work. For a source fsspec doesn't know, you can pass your own reader: any object withsize()andread_ranges(ranges).This runs as is against NASA's public HelioCloud bucket (
pip install pycdfpp[s3]):With no AWS credentials on the machine,
s3://reads anonymously, so public buckets need no setup. Credentials that exist are always used.storage_optionsgoes to fsspec and replaces this default.Settings
Every setting has a documented default. You can override it per call or with a
CDFPP_REMOTE_*environment variable, so a JupyterHub (HelioCloud) can preset them.read_ahead: 1 MiB by default. The reading guide explains why.tail_prefetchbacking: memory, or a temp filetemp_dirdownload_whole_below: opt-in only. Many small files read partially would cost more if each one were downloaded whole.Measured on HelioCloud (public S3)
The ACE file above is 53.6 MB. Downloading it whole and loading it takes 4.2 s. One round trip costs about 0.5 s from my machine. With the default settings, through fsspec:
Remote reads win when you open a file or read a few variables. Reading most of the file is slower than downloading it, because each variable's index is a chain of records, read one link at a time.
fsspec and obstore give the same numbers. The cost comes from round trips, not from Python, so a C++ transport isn't needed for now.
Other changes
wait_for_variable_lockhook invariable.hpp.Tests
remote_loading. It checks that every test resource loads the same through the remote path as from disk, eagerly and lazily, page by page. It also checks batching, corrupt offsets, truncated records, and the default window.python_loadingsuite also runs a second time through a reader.Before merging
subprojects/cpp_utils.wrappoints at cpp_utils main (29e4469), which now holds the remote-read code.meson wrap update.Left for later
🤖 Generated with Claude Code