Skip to content

Read InputStream bodies straight into the buffer, no staging array#2233

Open
pavel-ptashyts wants to merge 1 commit into
AsyncHttpClient:mainfrom
maygemdev:perf/inputstream-body-no-staging-copy
Open

Read InputStream bodies straight into the buffer, no staging array#2233
pavel-ptashyts wants to merge 1 commit into
AsyncHttpClient:mainfrom
maygemdev:perf/inputstream-body-no-staging-copy

Conversation

@pavel-ptashyts

Copy link
Copy Markdown
Contributor

InputStreamBodyGenerator's Body.transferTo allocated a fresh byte[] (sized to the target's writable region) on every call, read the stream into it, then copied those bytes into the target ByteBuf — a per-chunk allocation plus a redundant copy. Read directly into the target via ByteBuf.writeBytes(InputStream, int) instead (the same approach FileLikeMultipartPart uses), dropping both the staging array and the copy; the per-instance chunk field is gone.

Behaviour is unchanged: it writes the bytes read this call and returns CONTINUE while data remains, STOP at EOF or on an I/O error (logged, as before). The '- 10' writable margin is preserved.

Reachability note: AsyncHttpClient's own request path routes an InputStreamBodyGenerator to NettyInputStreamBody (NettyRequestFactory), so this Body is reached only through the public InputStreamBodyGenerator.createBody() API (external/custom callers); the change improves that path rather than pruning a public type.

Adds InputStreamBodyGeneratorTest covering byte-for-byte transfer across multiple reads, a single read draining a small stream, and immediate STOP on an empty stream. No public API change.

InputStreamBodyGenerator's Body.transferTo allocated a fresh byte[] (sized to the target's writable region) on every call, read the stream into it, then copied those bytes into the target ByteBuf — a per-chunk allocation plus a redundant copy. Read directly into the target via ByteBuf.writeBytes(InputStream, int) instead (the same approach FileLikeMultipartPart uses), dropping both the staging array and the copy; the per-instance chunk field is gone.

Behaviour is unchanged: it writes the bytes read this call and returns CONTINUE while data remains, STOP at EOF or on an I/O error (logged, as before). The '- 10' writable margin is preserved.

Reachability note: AsyncHttpClient's own request path routes an InputStreamBodyGenerator to NettyInputStreamBody (NettyRequestFactory), so this Body is reached only through the public InputStreamBodyGenerator.createBody() API (external/custom callers); the change improves that path rather than pruning a public type.

Adds InputStreamBodyGeneratorTest covering byte-for-byte transfer across multiple reads, a single read draining a small stream, and immediate STOP on an empty stream. No public API change. Fixes finding AsyncHttpClient#8.
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