Skip to content

docs(http_extensions): add allocation-efficient http client example - #788

Draft
martintmk wants to merge 3 commits into
mainfrom
martintmk-efficient-http-client-example
Draft

martintmk wants to merge 3 commits into
mainfrom
martintmk-efficient-http-client-example

Conversation

@martintmk

Copy link
Copy Markdown
Member

Adds examples/efficient_client.rs to http_extensions. It shows that the http crate is viable for allocation-sensitive clients: used deliberately, a full request/response round trip costs one small heap allocation.

Scenario

A mocked HTTP/1.1 client sends a request and receives a response. Each carries 10 headers and a 5 KiB body. The mocked connection delivers the response in 3-byte chunks. All byte data lives in GlobalPool memory managed through BytesBuf / BytesView: the payload, the outgoing request, the receive buffer and the canned response.

Techniques

  • Pooled buffers. Bytes are received into a pooled BytesBuf, and the request is written into pooled memory. The request body BytesView is appended without copying.
  • Shared header values. The full response head becomes one shared Bytes, and each header value is a slice of it created with HeaderValue::from_maybe_shared, so nothing is copied. Long-lived request values (authorization, correlation ID) are shared the same way. Static values use from_static.
  • Non-allocating header names. Standard names are recognized, and the one custom name is built once and reused.
  • HeaderMap reuse. The client splits the request into parts with into_parts() and clears the request's HeaderMap to hold the response headers. The caller then passes that map into the next request, so the map is allocated once.
  • Zero-copy response body. The body is returned as a BytesView over the receive buffer.

Report

Measured with alloc_tracker over 1,000 requests after a 100-request warm-up (cargo run -p http_extensions --example efficient_client --release):

Per-request heap usage (10 headers and 5120-byte bodies each way, response received in 3-byte chunks, 1000 requests):
operation                       allocations        bytes
1. efficient: build request             0.0          0.0
2. efficient: execute                   1.0         40.0
3. naive: build request                20.0       7386.0
4. naive: execute                      67.0      36512.0

efficient: round trip                   1.0         40.0
naive: round trip                      87.0      43898.0

The one remaining allocation (40 bytes) is the shared owner that BytesView::to_bytes() creates to wrap the pooled response head as Bytes. That's the only storage HeaderValue accepts. All 10 response header values reference this one owner.

The naive client uses the common convenience APIs (Request::builder() with string headers, format!, Vec<u8> buffers, HeaderValue::from_str), for comparison.

martintmk and others added 3 commits October 1, 2026 14:33
Demonstrates that the http crate is viable for allocation-sensitive clients:
a mocked HTTP/1.1 round trip with 10 headers and 5 KiB bodies each way,
received in 3-byte chunks, costs 2 heap allocations versus 89 for a naive client.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…lient example

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@codecov

codecov Bot commented Oct 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.0%. Comparing base (27a8b19) to head (e6e07c0).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #788      +/-   ##
==========================================
  Coverage   100.0%   100.0%              
==========================================
  Files         738       85     -653     
  Lines       98623     5446   -93177     
==========================================
- Hits        98623     5446   -93177     
Flag Coverage Δ
linux 100.0% <ø> (ø)
linux-arm 100.0% <ø> (ø)
scheduled ?
windows 100.0% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

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

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