Skip to content

blob/azureblob: parallel downloads via driver.DownloaderAt - #3808

Draft
stanhu wants to merge 5 commits into
google:masterfrom
stanhu:sh-azureblob-parallel-download
Draft

stanhu wants to merge 5 commits into
google:masterfrom
stanhu:sh-azureblob-parallel-download

Conversation

@stanhu

@stanhu stanhu commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Stacked on #3805 (which adds driver.DownloaderAt and the Bucket.Download routing); please review/merge that first. This PR's diff includes #3805's commit until it merges.

What

Implements driver.DownloaderAt in azureblob, so Bucket.Download into an *os.File fetches Azure blobs with parallel blocks instead of a single stream.

How

Uses the azblob DownloadFile helper, a method on the same *blob.Client the driver already uses for DownloadStream, so this adds no new import or dependency. It reuses the driver's existing client.

Azure's parallel download helpers only accept *os.File (DownloadFile) or []byte (DownloadBuffer); there is no parallel download into a generic io.WriterAt. So:

  • *os.File destination -> DownloadFile (parallel blocks).
  • any other io.WriterAt -> single sequential DownloadStream + copy, which is correct but not parallel.

The *os.File case is the common one (downloading to disk). BeforeRead exposes *blob.DownloadFileOptions / *blob.Client on the parallel path, and *blob.DownloadStreamOptions on the fallback.

Block size and concurrency use the azblob defaults; a follow-up can thread tunables through once #3806 (the ReaderOptions knobs) lands.

Testing

blob.Reader issues a single GET per object, so Bucket.Download streams
large objects on one connection and can't saturate available bandwidth.

Add an optional driver.DownloaderAt interface. When the download
destination is an io.WriterAt and the driver implements DownloaderAt,
Bucket.Download routes to it and skips opening a Reader, avoiding the
eager GET that NewRangeReader would issue and discard. Drivers that
don't implement it keep the existing single-stream behavior, and the
public API and driver.Bucket interface are unchanged.

Implement DownloaderAt in s3blob using the AWS transfer manager
(feature/s3/transfermanager), which this driver already depends on for
uploads. It fetches the object with concurrent ranged GETs written
directly to the destination offsets.

Issue: google#3804
Add TestDownloaderAt covering the three cases in Bucket.Download: an
io.WriterAt destination with a driver that implements DownloaderAt uses
DownloadAt; a non-io.WriterAt destination falls back to the reader even
when DownloaderAt is available; and an io.WriterAt destination with a
driver that lacks DownloaderAt falls back to the reader.
Download and Upload were added in 2023 but never folded into the blob
howto, which documents only NewReader/NewRangeReader for reading. Add an
ExampleBucket_Download that downloads into an *os.File (an io.WriterAt,
so the parallel path is used on S3) and reference it from the "Reading
data" section, alongside regenerating the examples.json entry.
Implement DownloadAt using the azblob DownloadFile helper, a method on
the same *blob.Client the driver already uses, so this adds no new
import or dependency. When the destination is an *os.File it downloads
the blob in parallel blocks; for any other io.WriterAt it falls back to
a single sequential stream, since azblob has no parallel download into a
generic io.WriterAt.

With this, blob.Bucket.Download into an *os.File fetches Azure blobs in
parallel instead of on a single stream.

Part of google#3804

This branch has not been deployed

No deployments
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.

1 participant