-
Notifications
You must be signed in to change notification settings - Fork 118
Description
Hello,
It seems not possible to add headers without allocations. Adding a header seems to be costing 6 (or 4) allocations.
Ideas
My initial thought was that the AddHeaders API is inefficient, but @jstroem below benchmarked this not be a problem.
type ResponseWriter interface {
io.Writer
AddHeaders(Headers)
however, transport.Headers always allocated two maps
type Headers struct {
items map[string]string
originalItems map[string]string
}
yarpc canonical headers are lowercase, while http canonical headers are capitalized.
This leads to a very paradoxical situation where:
if I add lower-case http header
resw.AddHeaders(transport.NewHeadersWithCapacity(1).With(
"abc", "",
))
I get:
BenchmarkRespWriter-12 2514664 462.6 ns/op 672 B/op 4 allocs/op
This means two allocations for the maps in transport.Headers, 1 allocation for addToMetadata, and possibly 1 https://pkg.go.dev/net/http#CanonicalHeaderKey - not sure if the last one is included in my benchmark though.
But if I do correct HTTP canonical headers, which should be better
resw.AddHeaders(transport.NewHeadersWithCapacity(1).With(
"Abc", "",
))
I get
BenchmarkRespWriter-12 2390634 446.2 ns/op 678 B/op 6 allocs/op
so it's worse - yarpc will convert my correct header to lower-case first (extra alloc) and one another extra alloc that I don't understand.
Possible solutions
There are a few options - which one would you recommend?
It would be relatively easy to add ResponseWriter.AddHeader(key, value string) - this would save me two allocations, leaving the remaining two.
AddRawHeader, or make AddSystemHeader public
In order to avoid Go triggering https://pkg.go.dev/net/http#CanonicalHeaderKey for me later on anyway, I would rather pass in HTTP canonical headers (Abc and not abc).
This means I would need something like ResponseWriter.AddRawHeader(key, value string) that wouldn't do transport.CanonicalizeHeaderKey for me. But I'm not sure about the other implications of doing this.
Anything else?
Please advise.