header.go Referer() optimize (#1313)

* args.go GetBool(): use switch with string casting

This should be optimized by Go compiler itself so the b2s() call is not needed.

It was previously done by this but changed in
1e7885eb56

* header.go Referer() optimize

Use direct peekArgBytes() instead of PeekBytes() that will check for special headers

* header_timing_test.go BenchmarkRequestHeaderPeekBytesSpecialHeader

The old BenchmarkRequestHeaderPeekBytesCanonical and BenchmarkRequestHeaderPeekBytesNonCanonical are in fact just measured the header normalization.
But it's anyway is benchmarked separately.
Results was almost the same: 1.5 ns/op.

Instead, let's reuse the benches to find a difference between peeking of special (Host, CT) and custom headers.
This commit is contained in:
Sergey Ponomarev
2022-06-06 09:46:49 +03:00
committed by GitHub
parent c9f43eaa1b
commit 66cd5022fd
3 changed files with 41 additions and 9 deletions
+1 -1
View File
@@ -343,7 +343,7 @@ func (a *Args) GetUfloatOrZero(key string) float64 {
// true is returned for "1", "t", "T", "true", "TRUE", "True", "y", "yes", "Y", "YES", "Yes",
// otherwise false is returned.
func (a *Args) GetBool(key string) bool {
switch b2s(a.Peek(key)) {
switch string(a.Peek(key)) {
// Support the same true cases as strconv.ParseBool
// See: https://github.com/golang/go/blob/4e1b11e2c9bdb0ddea1141eed487be1a626ff5be/src/strconv/atob.go#L12
// and Y and Yes versions.
+1 -1
View File
@@ -586,7 +586,7 @@ func (h *RequestHeader) SetUserAgentBytes(userAgent []byte) {
// Referer returns Referer header value.
func (h *RequestHeader) Referer() []byte {
return h.PeekBytes(strReferer)
return peekArgBytes(h.h, strReferer)
}
// SetReferer sets Referer header value.
+39 -7
View File
@@ -12,6 +12,9 @@ import (
var strFoobar = []byte("foobar.com")
// it has the same length as Content-Type
var strNonSpecialHeader = []byte("Dontent-Type")
type benchReadBuf struct {
s []byte
n int
@@ -96,12 +99,13 @@ func BenchmarkResponseHeaderWrite(b *testing.B) {
})
}
func BenchmarkRequestHeaderPeekBytesCanonical(b *testing.B) {
// Result: 2.2 ns/op
func BenchmarkRequestHeaderPeekBytesSpecialHeader(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
var h RequestHeader
h.SetBytesV("Host", strFoobar)
h.SetContentTypeBytes(strFoobar)
for pb.Next() {
v := h.PeekBytes(strHost)
v := h.PeekBytes(strContentType)
if !bytes.Equal(v, strFoobar) {
b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
}
@@ -109,13 +113,41 @@ func BenchmarkRequestHeaderPeekBytesCanonical(b *testing.B) {
})
}
func BenchmarkRequestHeaderPeekBytesNonCanonical(b *testing.B) {
// Result: 2.9 ns/op
func BenchmarkRequestHeaderPeekBytesNonSpecialHeader(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
var h RequestHeader
h.SetBytesV("Host", strFoobar)
hostBytes := []byte("HOST")
h.SetBytesKV(strNonSpecialHeader, strFoobar)
for pb.Next() {
v := h.PeekBytes(hostBytes)
v := h.PeekBytes(strNonSpecialHeader)
if !bytes.Equal(v, strFoobar) {
b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
}
}
})
}
// Result: 2.3 ns/op
func BenchmarkResponseHeaderPeekBytesSpecialHeader(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
var h ResponseHeader
h.SetContentTypeBytes(strFoobar)
for pb.Next() {
v := h.PeekBytes(strContentType)
if !bytes.Equal(v, strFoobar) {
b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
}
}
})
}
// Result: 2.9 ns/op
func BenchmarkResponseHeaderPeekBytesNonSpecialHeader(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
var h ResponseHeader
h.SetBytesKV(strNonSpecialHeader, strFoobar)
for pb.Next() {
v := h.PeekBytes(strNonSpecialHeader)
if !bytes.Equal(v, strFoobar) {
b.Fatalf("unexpected result: %q. Expected %q", v, strFoobar)
}