Skip to content

Implement native adjacent byte range coalescing in cat_ranges - #1024

Open
yuxin00j wants to merge 26 commits into
fsspec:mainfrom
yuxin00j:feature-cat-ranges-coalesce
Open

Implement native adjacent byte range coalescing in cat_ranges#1024
yuxin00j wants to merge 26 commits into
fsspec:mainfrom
yuxin00j:feature-cat-ranges-coalesce

Conversation

@yuxin00j

@yuxin00j yuxin00j commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR implements native byte range coalescing for GCSFileSystem.cat_ranges and ExtendedGcsFileSystem.cat_ranges to optimize chunk-based workload downloads (such as PyTorch Distributed Checkpoint / DCP payload loading).

Adjacent and near-adjacent byte requests on the same object are coalesced into singular block reads natively, reducing request amplification and leveraging zero-copy memoryview slicing.

Key Changes

  • Core Coalescing & Unpacking Helpers (gcsfs/core.py):

    • _coalesce_ranges: Groups and merges overlapping, contiguous (max_gap=0), and near-contiguous (gap <= max_gap) range requests for a given file, generating relative slice offsets mapped to caller indices.
    • _merge_file_ranges & _is_coalesce_enabled: Unifies conditional coalescing vs 1-to-1 range mapping.
    • _unpack_range_results: Safely populates caller results with bytes when coalescing is inactive (max_gap is None or < 0) or memoryview slices when active (max_gap >= 0).
    • Safely handles bounded and unbounded ranges (end=None), empty inputs, scalar broadcasting, and separate non-overlapping clusters.
  • GCSFileSystem._cat_ranges (gcsfs/core.py):

    • Adds native support for coalesced byte range reads across multiple files.
    • Executes chunked reads using asyn._run_coros_in_chunks respecting batch_size.
    • Normalizes iterable/generator inputs for starts and ends.
    • Supports both on_error="return" and on_error="raise" error modes.
  • ExtendedGcsFileSystem._cat_ranges (gcsfs/extended_gcsfs.py):

    • Bulk Zonal Downloads via MRD: Connects range coalescing with Zonal (RAPID) buckets via AsyncMultiRangeDownloader (MRD).
    • Dynamic Multi-MRD Pool Concurrency: Sizes pool_size = min(max_batches, max(1, concurrency)) to stream multiple batches in parallel across pooled MRDs, avoiding head-of-line blocking and single-stream throughput bottlenecks on large multi-gigabyte transfers.
    • Unified Coroutine Scheduling: Combines Zonal MRD batch downloads and Non-Zonal HTTP GETs into a single coroutine pool scheduled via asyn._run_coros_in_chunks, providing global concurrency throttling.
    • Lazy Metadata Lookup: Queries object metadata (_info()) only when unbounded ranges (end=None or negative offsets) require file size resolution.
    • Resource Cleanup: Ensures all acquired MRDPool instances are cleanly closed in finally blocks upon completion or failure.

Testing

  • Unit Tests in gcsfs/tests/test_core.py:
    • Parameterized tests for _coalesce_ranges covering single, contiguous, overlapping, unordered, unbounded, and multi-cluster cases.
    • Integration tests for input validation, scalar broadcasting, contiguous coalescing (max_gap=0), multi-file coalescing, and error modes.
  • Unit Tests in gcsfs/tests/test_extended_gcsfs.py:
    • Tests for non-zonal delegation, zonal coalescing with MockMRD, mixed zonal/non-zonal paths in a single call, partial batch failure preservation, and lazy metadata validation.
    • Tests for dynamic MRD pool concurrency, chunk-based batch size limits via _run_coros_in_chunks, return types (bytes vs memoryview), and pool cleanup upon error.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements _cat_ranges and cat_ranges in both GCSFileSystem and ExtendedGcsFileSystem to fetch multiple byte ranges efficiently, supporting range coalescing and leveraging AsyncMultiRangeDownloader for zonal buckets. It also adds comprehensive unit tests. The review feedback suggests extracting the duplicated input validation logic into a shared helper and removing an unnecessary fallback default value of 64 for the batch size.

Comment thread gcsfs/extended_gcsfs.py Outdated
Comment thread gcsfs/extended_gcsfs.py Outdated
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.72385% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.26%. Comparing base (8a3d3f5) to head (2e472db).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
gcsfs/core.py 94.73% 8 Missing ⚠️
gcsfs/extended_gcsfs.py 91.95% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1024      +/-   ##
==========================================
+ Coverage   90.10%   90.26%   +0.15%     
==========================================
  Files          16       16              
  Lines        3679     3902     +223     
==========================================
+ Hits         3315     3522     +207     
- Misses        364      380      +16     

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

@yuxin00j

Copy link
Copy Markdown
Collaborator Author

/gcbrun

Comment thread gcsfs/extended_gcsfs.py Outdated
Comment thread gcsfs/extended_gcsfs.py Outdated
Comment thread gcsfs/core.py Outdated
Comment thread gcsfs/extended_gcsfs.py Outdated
Comment thread gcsfs/extended_gcsfs.py Outdated
Comment thread gcsfs/extended_gcsfs.py Outdated
@yuxin00j

Copy link
Copy Markdown
Collaborator Author

/gcbrun

@yuxin00j
yuxin00j requested a review from zhixiangli August 28, 2026 09:41
…m.cat_ranges

Optimizes Fsspec DCP payload downloads by heavily coalescing contiguous/adjacent data chunks into singular block reads natively within _cat_ranges, preventing multi-shard GET amplification. Support includes zero-copy memoryview splicing.
- Fix TypeError on unbounded ranges in _coalesce_ranges when end=None
- Fix batch exception scoping in ExtendedGcsFileSystem._cat_ranges
- Support contiguous range coalescing when max_gap=0
- Lazily query object metadata only when unbounded ranges are present
- Execute zonal and non-zonal bucket fetches concurrently
- Add unit tests for middle unbounded ranges, empty inputs, mixed buckets, and partial batch failures
… lifecycle

- Ensure mrd_pool is properly closed in try...finally block in _fetch_zonal_file
- Move _process_limits_to_offset_and_length to GCSFileSystem and normalize limits before coalescing
- Return empty bytes directly for zero-length slices without issuing I/O
- Support batch_size=-1 for unchunked execution and cap effective_batch_size at 1000
- Bound concurrent zonal file download jobs with asyncio.Semaphore
- Add unit tests for pool cleanup, normalization, and batch_size=-1
…ne fast path, and return types

- Support tuple of paths in _validate_cat_ranges_input
- Handle s is None (offset 0) in fast path without triggering unhandled _info calls
- Honor caller batch_size for outer file_concurrency semaphore in ExtendedGcsFileSystem
- Ensure bytes return type in ExtendedGcsFileSystem when max_gap is None
- Add unit tests for tuple paths, start=None lazy info and error handling, and batch_size semaphore
…_size helpers

- Centralize per-file range limit normalization, fast-path, and zero-length slice handling in GCSFileSystem._normalize_file_ranges
- Eliminate duplicate normalization block in ExtendedGcsFileSystem._cat_ranges by reusing inherited _normalize_file_ranges with get_size_fn
- Centralize bounded batch size computation in _compute_effective_batch_size
- Add unit test for _normalize_file_ranges helper
- Merge tuple paths into test_gcsfs_cat_ranges_validation
- Merge start=None normalization into test_gcsfs_cat_ranges_normalization
- Merge start=None error handling into test_gcsfs_cat_ranges_error_handling
- Merge zonal start=None lazy info into test_extended_gcsfs_cat_ranges_zonal_lazy_info
- Merge zonal pool error handling into test_extended_gcsfs_cat_ranges_zonal_error_handling
@zhixiangli
zhixiangli force-pushed the feature-cat-ranges-coalesce branch from 9bf4ea9 to 799cdd1 Compare August 28, 2026 10:05
Comment thread gcsfs/core.py
@yuxin00j
yuxin00j force-pushed the feature-cat-ranges-coalesce branch from fa21041 to 495e363 Compare August 31, 2026 05:07
@yuxin00j
yuxin00j force-pushed the feature-cat-ranges-coalesce branch from 495e363 to ef9f758 Compare August 31, 2026 05:10
@yuxin00j
yuxin00j requested a review from zhixiangli August 31, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants