From 66cd5022fdfb02e619e1b556d1e55fe1f42dac90 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 6 Jun 2022 09:46:49 +0300 Subject: [PATCH] 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 1e7885eb56cdf4c6f550e143b0dbd3acc82a4137 * 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. --- args.go | 2 +- header.go | 2 +- header_timing_test.go | 46 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/args.go b/args.go index dc10ea1..86dc7b9 100644 --- a/args.go +++ b/args.go @@ -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. diff --git a/header.go b/header.go index fc61ae2..e7616df 100644 --- a/header.go +++ b/header.go @@ -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. diff --git a/header_timing_test.go b/header_timing_test.go index 0d7ab67..81ff7fb 100644 --- a/header_timing_test.go +++ b/header_timing_test.go @@ -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) }