mirror of https://github.com/golang/go.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 <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
2c802e9980
commit
6b7114b9e5
|
|
@ -230,25 +230,28 @@ func (c *Cookie) String() string {
|
||||||
//
|
//
|
||||||
// if filter isn't empty, only cookies of that name are returned
|
// if filter isn't empty, only cookies of that name are returned
|
||||||
func readCookies(h Header, filter string) []*Cookie {
|
func readCookies(h Header, filter string) []*Cookie {
|
||||||
lines, ok := h["Cookie"]
|
lines := h["Cookie"]
|
||||||
if !ok {
|
if len(lines) == 0 {
|
||||||
return []*Cookie{}
|
return []*Cookie{}
|
||||||
}
|
}
|
||||||
|
|
||||||
cookies := []*Cookie{}
|
cookies := make([]*Cookie, 0, len(lines)+strings.Count(lines[0], ";"))
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
parts := strings.Split(strings.TrimSpace(line), ";")
|
line = strings.TrimSpace(line)
|
||||||
if len(parts) == 1 && parts[0] == "" {
|
|
||||||
|
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
|
continue
|
||||||
}
|
}
|
||||||
// Per-line attributes
|
name, val := part, ""
|
||||||
for i := 0; i < len(parts); i++ {
|
if j := strings.Index(part, "="); j >= 0 {
|
||||||
parts[i] = strings.TrimSpace(parts[i])
|
|
||||||
if len(parts[i]) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name, val := parts[i], ""
|
|
||||||
if j := strings.Index(name, "="); j >= 0 {
|
|
||||||
name, val = name[:j], name[j+1:]
|
name, val = name[:j], name[j+1:]
|
||||||
}
|
}
|
||||||
if !isCookieNameValid(name) {
|
if !isCookieNameValid(name) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue