From eacc8e8b6c597a9f21aa46971bdfa7cfd39fbcc8 Mon Sep 17 00:00:00 2001 From: jub0bs Date: Fri, 9 Feb 2024 11:21:38 +0100 Subject: [PATCH 1/2] Fix skewed middleware benchmarks (#165) --- bench_test.go | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/bench_test.go b/bench_test.go index 92815cc..d8eeac0 100644 --- a/bench_test.go +++ b/bench_test.go @@ -29,19 +29,18 @@ const ( ) func BenchmarkWithout(b *testing.B) { - res := FakeResponse{http.Header{}} + resps := makeFakeResponses(b.N) req, _ := http.NewRequest(http.MethodGet, dummyEndpoint, nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - clear(res.header) - testHandler.ServeHTTP(res, req) + testHandler.ServeHTTP(resps[i], req) } } func BenchmarkDefault(b *testing.B) { - res := FakeResponse{http.Header{}} + resps := makeFakeResponses(b.N) req, _ := http.NewRequest(http.MethodGet, dummyEndpoint, nil) req.Header.Add(headerOrigin, dummyOrigin) handler := Default().Handler(testHandler) @@ -49,13 +48,12 @@ func BenchmarkDefault(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - clear(res.header) - handler.ServeHTTP(res, req) + handler.ServeHTTP(resps[i], req) } } func BenchmarkAllowedOrigin(b *testing.B) { - res := FakeResponse{http.Header{}} + resps := makeFakeResponses(b.N) req, _ := http.NewRequest(http.MethodGet, dummyEndpoint, nil) req.Header.Add(headerOrigin, dummyOrigin) c := New(Options{ @@ -66,13 +64,12 @@ func BenchmarkAllowedOrigin(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - clear(res.header) - handler.ServeHTTP(res, req) + handler.ServeHTTP(resps[i], req) } } func BenchmarkPreflight(b *testing.B) { - res := FakeResponse{http.Header{}} + resps := makeFakeResponses(b.N) req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil) req.Header.Add(headerOrigin, dummyOrigin) req.Header.Add(headerACRM, http.MethodGet) @@ -81,13 +78,12 @@ func BenchmarkPreflight(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - clear(res.header) - handler.ServeHTTP(res, req) + handler.ServeHTTP(resps[i], req) } } func BenchmarkPreflightHeader(b *testing.B) { - res := FakeResponse{http.Header{}} + resps := makeFakeResponses(b.N) req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil) req.Header.Add(headerOrigin, dummyOrigin) req.Header.Add(headerACRM, http.MethodGet) @@ -97,13 +93,14 @@ func BenchmarkPreflightHeader(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - clear(res.header) - handler.ServeHTTP(res, req) + handler.ServeHTTP(resps[i], req) } } -func clear(h http.Header) { - for k := range h { - delete(h, k) +func makeFakeResponses(n int) []*FakeResponse { + resps := make([]*FakeResponse, n) + for i := 0; i < n; i++ { + resps[i] = &FakeResponse{http.Header{}} } + return resps } From 0bcf73f5c969d9ae35f1ed986ab27fbb37a58ff2 Mon Sep 17 00:00:00 2001 From: Olivier Poitrey Date: Sat, 10 Feb 2024 00:34:16 +0100 Subject: [PATCH 2/2] Update benchmark Also initialize the response headers with the default header in benchmarks as all reponse at least have one header. This removes the single allocation that should not be attributed to this library. Also add a micro-optimization on the critical path. --- README.md | 16 ++++++++-------- bench_test.go | 4 +++- cors.go | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f92e8e6..6bc95a5 100644 --- a/README.md +++ b/README.md @@ -106,15 +106,15 @@ See [API documentation](http://godoc.org/github.com/rs/cors) for more info. goos: darwin goarch: arm64 pkg: github.com/rs/cors -BenchmarkWithout-10 352671961 3.317 ns/op 0 B/op 0 allocs/op -BenchmarkDefault-10 18261723 65.63 ns/op 0 B/op 0 allocs/op -BenchmarkAllowedOrigin-10 13309591 90.21 ns/op 0 B/op 0 allocs/op -BenchmarkPreflight-10 7247728 166.9 ns/op 0 B/op 0 allocs/op -BenchmarkPreflightHeader-10 5915437 202.9 ns/op 0 B/op 0 allocs/op -BenchmarkWildcard/match-10 250336476 4.784 ns/op 0 B/op 0 allocs/op -BenchmarkWildcard/too_short-10 1000000000 0.6354 ns/op 0 B/op 0 allocs/op +BenchmarkWithout-10 135325480 8.124 ns/op 0 B/op 0 allocs/op +BenchmarkDefault-10 24082140 51.40 ns/op 0 B/op 0 allocs/op +BenchmarkAllowedOrigin-10 16424518 88.25 ns/op 0 B/op 0 allocs/op +BenchmarkPreflight-10 8010259 147.3 ns/op 0 B/op 0 allocs/op +BenchmarkPreflightHeader-10 6850962 175.0 ns/op 0 B/op 0 allocs/op +BenchmarkWildcard/match-10 253275342 4.714 ns/op 0 B/op 0 allocs/op +BenchmarkWildcard/too_short-10 1000000000 0.6235 ns/op 0 B/op 0 allocs/op PASS -ok github.com/rs/cors 9.613s +ok github.com/rs/cors 99.131s ``` ## Licenses diff --git a/bench_test.go b/bench_test.go index d8eeac0..6859382 100644 --- a/bench_test.go +++ b/bench_test.go @@ -100,7 +100,9 @@ func BenchmarkPreflightHeader(b *testing.B) { func makeFakeResponses(n int) []*FakeResponse { resps := make([]*FakeResponse, n) for i := 0; i < n; i++ { - resps[i] = &FakeResponse{http.Header{}} + resps[i] = &FakeResponse{http.Header{ + "Content-Type": []string{"text/plain"}, + }} } return resps } diff --git a/cors.go b/cors.go index 9a8b419..e084128 100644 --- a/cors.go +++ b/cors.go @@ -394,10 +394,10 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { allowed, additionalVaryHeaders := c.isOriginAllowed(r, origin) // Always set Vary, see https://github.com/rs/cors/issues/10 - if vary, found := headers["Vary"]; found { - headers["Vary"] = append(vary, headerVaryOrigin[0]) - } else { + if vary := headers["Vary"]; vary == nil { headers["Vary"] = headerVaryOrigin + } else { + headers["Vary"] = append(vary, headerVaryOrigin[0]) } if len(additionalVaryHeaders) > 0 { headers.Add("Vary", strings.Join(convert(additionalVaryHeaders, http.CanonicalHeaderKey), ", "))