Skip to content

net/http: reduce allocations in (Header).clone #29915

Closed
@NWilson

Description

@NWilson

What version of Go are you using (go version)?

go version go1.11.2 linux/amd64

Does this issue reproduce with the latest release?

Yes

What did you do?

When using net/http's server, and profiling with pprof shows that the "Header.clone" function takes up a lot of allocations (4% of my application's allocations, actually).

Solution

Could we improve the function to perform fewer allocations!

(NB. Note that Reader.ReadMIMEHeader in net/textproto already uses exactly this same trick, of using three-argument slicing to build the http.Header using a single []string. So the pattern already exists in the codebase.)

--- /tmp/header-v1.go   2019-01-24 11:18:01.182761218 +0000
+++ /tmp/header-v2.go   2019-01-24 11:17:42.367569268 +0000
@@ -1,9 +1,17 @@
 func (h Header) clone() Header {
  h2 := make(Header, len(h))
+ sliceLen := 0
+ for _, vv := range h {
+  sliceLen += len(vv)
+ }
+ slice := make([]string, sliceLen)
+ sliceLen = 0
  for k, vv := range h {
-  vv2 := make([]string, len(vv))
+  vv2 := slice[sliceLen:sliceLen+len(vv):sliceLen+len(vv)]
+  sliceLen += len(vv)
   copy(vv2, vv)
   h2[k] = vv2
  }
  return h2
 }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions