Skip to content

Direct buffer pool streaming download in the CRT-based S3 client - #7472

Open
davidh44 wants to merge 4 commits into
feature/master/dbz-poolfrom
dbz-pool
Open

davidh44 wants to merge 4 commits into
feature/master/dbz-poolfrom
dbz-pool

Conversation

@davidh44

Copy link
Copy Markdown
Contributor

Motivation and Context

getObject(request, AsyncResponseTransformer.toBlockingInputStream()) on the CRT-based S3 client copies every downloaded part from native memory into a new heap byte[]. For large, slow, concurrent downloads that results in sustained heap allocation and GC pressure. aws-crt-java is adding a new feature that adds a direct buffer pool that can lend part buffers to a response handler instead of copying them.

This PR targets feature/master/dbz-pool branch. It depends on a future aws-crt-java release that contains the direct buffer pool feature, so CI checks are expected to fail until a released version is available and the SDK dependency is bumped.

Transfer Manager support follows in a separate PR.

Modifications

  • Add S3CrtDirectBufferPoolConfiguration with auto(), fixed(long) and elastic(long, long), and S3CrtAsyncClientBuilder.directBufferPoolConfiguration(...) to attach a pool to the CRT client.
  • Add S3CrtAsyncResponseTransformer.toBlockingInputStreamFromDirectBufferPool(). On a CRT client with a pool, it returns a ResponseInputStream that reads CRT's direct buffers and releases each one, and credits the read window, once it has been read. read(byte[]) still copies into the caller's array. GetObject requests with partNumber use separately allocated native memory instead of the pool.
  • Each transformer is for one getObject call. The request fails before it is sent on a client without a pool, on the Java-based S3 client, when the transformer is wrapped, or when a transformer is reused.

Behavior changes

  • None for clients that don't set directBufferPoolConfiguration.
  • With a pool, ordinary downloads and multipart uploads on that client share its capacity, so a slow reader of a pooled download can delay them.
  • With a pool, a configured minimumPartSizeInBytes is used as set, so a multipart upload fails before sending data if it is below 5 MiB or the object needs more than 10,000 parts. Without a configured part size, a fixed pool limits a known-size multipart upload to 312.5 GiB, or less for a pool smaller than 32 MiB.
  • With a pool, client creation fails if minimumPartSizeInBytes exceeds the pool's part-size limit, or if a fixed() or elastic() ceiling does not fit within 80% of -XX:MaxDirectMemorySize.
  • Downloads that use toBlockingInputStreamFromDirectBufferPool() don't apply modifyAsyncHttpResponseContent to the object body.

Testing

  • Added unit and WireMock tests for the stream, buffer release and read-window credit, range validation, cancellation, timeouts, error responses, cross-region redirects, partNumber, transformer reuse and pool configuration.

Screenshots (if appropriate)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the CONTRIBUTING document
  • Local run of mvn install succeeds
  • My code follows the code style of this project
  • My change requires a change to the Javadoc documentation
  • I have updated the Javadoc documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed
  • I have added a changelog entry. Adding a new entry must be accomplished by running the scripts/new-change script and following the instructions. Commit the new file created by the script in .changes/next-release with your changes.
  • My change is to implement 1.11 parity feature and I have updated LaunchChangelog

License

  • I confirm that this pull request can be released under the Apache 2 license

@davidh44
davidh44 requested a review from a team as a code owner October 22, 2026 00:46

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