Skip to content

[HTTP]Feat: pool for http headers path - #2486

Open
pulkit4tech wants to merge 2 commits into
mainfrom
perf-http-header-pool
Open

[HTTP]Feat: pool for http headers path#2486
pulkit4tech wants to merge 2 commits into
mainfrom
perf-http-header-pool

Conversation

@pulkit4tech

Copy link
Copy Markdown
Collaborator
  • Description and context for reviewers: one partner, one stranger

Problem

Every outbound RPC call allocates a fresh http.Header map in
createRequestToHTTPHeaders. This map is used only to build
and send request headers; after roundTrip returns it is garbage.
In high-throughput services this is a steady stream of short-lived
allocations that pressure the GC.

Solution

Add a package-level sync.Pool of pre-sized http.Header maps
(capacity 16 — enough for YARPC core headers + typical application
headers without growing the backing hash table). Each call() borrows
a map from the pool, passes it through createRequest
ToHTTPHeaders, then clears and returns it via defer after
roundTrip completes.

net/http serialises request headers to the wire inside roundTrip;
no code path in call() reads the request header map after that
returns, so pool reuse is safe.

Changes

File Change
transport/http/outbound.go headerPool (sync.Pool), _headerPoolInitSize = 16; call() borrows/returns map via defer; createRequest accepts pre-allocated http.Header
transport/http/outbound_test.go Update createRequest call to pass header map
transport/http/createrequest_bench_test.go Update createRequest calls to pass header map

Benchmarks

End-to-end, -benchmem -benchtime=3s, AMD EPYC 7B13, Go 1.26.1:

BenchmarkHeaderAlloc_EndToEnd_NoAppHeaders 141 → 139 allocs/op (-2) 14302 → 13894 B/op (-408 B)
BenchmarkHeaderAlloc_EndToEnd_10AppHeaders 201 → 195 allocs/op (-6) 21355 → 19052 B/op (-2303 B)

RELEASE NOTES: Pool http.Header maps on the outbound hot path, saving allocations and memory per RPC call

@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.22%. Comparing base (78bf565) to head (144d489).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2486      +/-   ##
==========================================
- Coverage   85.23%   85.22%   -0.01%     
==========================================
  Files         281      281              
  Lines       16773    16784      +11     
==========================================
+ Hits        14296    14305       +9     
- Misses       2015     2016       +1     
- Partials      462      463       +1     

☔ View full report in Codecov by Sentry.
📢 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.

urlTemplate, _ := url.Parse("http://my-service.prod.uber.internal:8080/v1")
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what about upgrading yarpc to a modern go? :)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

sure, will do it as follow-up :) Thanks!

Comment thread transport/http/createrequest_bench_test.go Outdated
Comment thread transport/http/createrequest_bench_test.go Outdated
@pulkit4tech
pulkit4tech force-pushed the perf-http-header-pool branch from 783fcdf to 144d489 Compare May 12, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants