Skip to content

perf(cache): parallelize large S3 range reads#387

Open
worstell wants to merge 1 commit into
mainfrom
worstell/s3-parallel-ranged-reads
Open

perf(cache): parallelize large S3 range reads#387
worstell wants to merge 1 commit into
mainfrom
worstell/s3-parallel-ranged-reads

Conversation

@worstell

@worstell worstell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Full-object S3 reads already fan out across parallel range GETs, but a ranged read was served as a single S3 stream capped at a fraction of available bandwidth. Chunked clients (e.g. the parallel git-snapshot restore) issuing ranged reads against an object that must be served from S3 therefore paid a structural penalty per chunk.

Large ranged reads now fan out too: the requested range is split into parts fetched concurrently, scaling the part size down (to a 4MiB floor) so ranges smaller than one configured download part still use multiple streams. Small ranges (<8MiB) keep the single-stream path. All requests are pinned to the same object revision via ETag.

There is no S3-internal parallelisation engine: both the full-object and ranged paths drive the existing client.ParallelGet machinery through a small RangeReader adapter that maps window-relative ranges onto pinned S3 range GETs. This reuses ParallelGet's dispatch gating and bounded stream reassembly, so a consumer slower than the aggregate download rate applies backpressure to the workers instead of letting chunks pile up in RAM; peak memory is bounded at 2 × download-concurrency × part size regardless of object size.

In end-to-end testing of cold-cache restores of a large repository, this cut restore time by ~38% and raised per-serve bandwidth ~2.7×.

@worstell worstell changed the title Parallel sub-range requests for large S3 ranged reads perf(cache): parallel sub-range requests for large S3 ranged reads Jul 14, 2026
@worstell
worstell force-pushed the worstell/s3-parallel-ranged-reads branch from 07ef9f7 to 3ade69d Compare July 14, 2026 21:15
@worstell
worstell marked this pull request as ready for review July 14, 2026 21:15
@worstell
worstell requested a review from a team as a code owner July 14, 2026 21:15
@worstell
worstell requested review from jrobotham-square and removed request for a team July 14, 2026 21:15

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

ℹ️ 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 internal/cache/s3_parallel_get_internal_test.go Outdated
@worstell
worstell force-pushed the worstell/s3-parallel-ranged-reads branch from 3ade69d to 0ba43f7 Compare July 14, 2026 21:42
@alecthomas

Copy link
Copy Markdown
Collaborator

I actually have no idea what a "sub-range" request is, as opposed to just a range request, but instead of this, can we replace all the internal S3 parallelisation with our existing range reader machinery?

That was what I was planning to do after getting all the other range reading working.

ie. delete the internal S3 parallelisation and instead use ParallelGet in the Tiered backend for syncing the lower tiers

@worstell
worstell force-pushed the worstell/s3-parallel-ranged-reads branch from 0ba43f7 to e6cb5f6 Compare July 15, 2026 18:00

@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: e6cb5f6ae0

ℹ️ 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 client/parallel_get.go
Full-object S3 reads already fan out across parallel range GETs, but a
ranged read was served as one single-stream S3 GET capped at a fraction
of available bandwidth. Clients issuing ranged reads against an object
that must be served from S3 therefore paid a structural penalty per
chunk.

Large ranges now split into parallel sub-range requests, scaling the
part size down (to a 4MiB floor) so ranges smaller than one configured
part still fan out. Small ranges keep the single-stream path, and all
sub-range requests remain etag-pinned.

Parallel downloads also now bound run-ahead: a token window caps
fetched-but-unwritten chunks at 2 x workers, so a consumer slower than
the aggregate download rate applies backpressure instead of letting
chunks pile up in RAM. Peak memory is 2 x DownloadConcurrency x part
size regardless of object size.
@worstell
worstell force-pushed the worstell/s3-parallel-ranged-reads branch from e6cb5f6 to bb09887 Compare July 15, 2026 18:12
@worstell worstell changed the title perf(cache): parallel sub-range requests for large S3 ranged reads perf(cache): parallelize large S3 range reads Jul 15, 2026
@@ -0,0 +1,135 @@
// Command lint-test-comments enforces the AGENTS.md rule that top-level tests

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lol

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't know how useful this is in practice. I wonder if we should just rely on codex? ie. comments can still be completely useless, even if they're in the right location

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