From: sergey Date: Sun, 24 Feb 2019 11:26:55 +0000 (+0300) Subject: net/http: speed up parsing of Cookie headers X-Git-Tag: go1.13beta1~693 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6b7114b9e5d872fe981a5c988915e4440f8df59c;p=gostls13.git net/http: speed up parsing of Cookie headers Parse the headers without splitting them upfront to reduce memory allocations. For non-pathological Cookie headers we can make a good estimate of the number of cookies in there and preallocate the slice of cookies name old time/op new time/op delta CookieString-4 1.73µs ± 2% 1.70µs ± 5% ~ (p=0.841 n=5+5) ReadSetCookies-4 6.09µs ± 3% 5.93µs ± 3% ~ (p=0.095 n=5+5) ReadCookies-4 7.63µs ± 1% 6.41µs ± 4% -15.99% (p=0.008 n=5+5) name old alloc/op new alloc/op delta CookieString-4 360B ± 0% 360B ± 0% ~ (all equal) ReadSetCookies-4 976B ± 0% 976B ± 0% ~ (all equal) ReadCookies-4 2.17kB ± 0% 1.84kB ± 0% -15.13% (p=0.008 n=5+5) name old allocs/op new allocs/op delta CookieString-4 5.00 ± 0% 5.00 ± 0% ~ (all equal) ReadSetCookies-4 15.0 ± 0% 15.0 ± 0% ~ (all equal) ReadCookies-4 16.0 ± 0% 11.0 ± 0% -31.25% (p=0.008 n=5+5) Change-Id: Ica1ca0d40c0d8d275134d1dfafb73f1082115826 Reviewed-on: https://go-review.googlesource.com/c/go/+/163617 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- diff --git a/src/net/http/cookie.go b/src/net/http/cookie.go index b8bc72b622..7d02796f30 100644 --- a/src/net/http/cookie.go +++ b/src/net/http/cookie.go @@ -230,25 +230,28 @@ func (c *Cookie) String() string { // // if filter isn't empty, only cookies of that name are returned func readCookies(h Header, filter string) []*Cookie { - lines, ok := h["Cookie"] - if !ok { + lines := h["Cookie"] + if len(lines) == 0 { return []*Cookie{} } - cookies := []*Cookie{} + cookies := make([]*Cookie, 0, len(lines)+strings.Count(lines[0], ";")) for _, line := range lines { - parts := strings.Split(strings.TrimSpace(line), ";") - if len(parts) == 1 && parts[0] == "" { - continue - } - // Per-line attributes - for i := 0; i < len(parts); i++ { - parts[i] = strings.TrimSpace(parts[i]) - if len(parts[i]) == 0 { + line = strings.TrimSpace(line) + + var part string + for len(line) > 0 { // continue since we have rest + if splitIndex := strings.Index(line, ";"); splitIndex > 0 { + part, line = line[:splitIndex], line[splitIndex+1:] + } else { + part, line = line, "" + } + part = strings.TrimSpace(part) + if len(part) == 0 { continue } - name, val := parts[i], "" - if j := strings.Index(name, "="); j >= 0 { + name, val := part, "" + if j := strings.Index(part, "="); j >= 0 { name, val = name[:j], name[j+1:] } if !isCookieNameValid(name) {