From: Blake Mizerany Date: Mon, 23 Jan 2017 19:03:03 +0000 (-0800) Subject: net/http/httputil: eliminate duplicate alloc/copy in ReverseProxy X-Git-Tag: go1.9beta1~1810 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b48c419c4109a1c0e1e7a60a7a28659f6a92e827;p=gostls13.git net/http/httputil: eliminate duplicate alloc/copy in ReverseProxy This commit elimates the request allocation and shallow copy duplication already done by req.WithContext. name old time/op new time/op delta ServeHTTP-4 216µs ±36% 212µs ±15% ~ (p=0.853 n=10+10) name old alloc/op new alloc/op delta ServeHTTP-4 917kB ±36% 1137kB ± 0% ~ (p=0.352 n=10+10) name old allocs/op new allocs/op delta ServeHTTP-4 5.00 ± 0% 4.00 ± 0% -20.00% (p=0.000 n=10+10) Change-Id: I514a59c30b037c7a65c355b06fd82c2d6ff17bb0 Reviewed-on: https://go-review.googlesource.com/35569 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 79c8fe2770..60b94d7649 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -149,12 +149,10 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { }() } - outreq := new(http.Request) - *outreq = *req // includes shallow copies of maps, but okay + outreq := req.WithContext(ctx) // includes shallow copies of maps, but okay if req.ContentLength == 0 { outreq.Body = nil // Issue 16036: nil Body for http.Transport retries } - outreq = outreq.WithContext(ctx) p.Director(outreq) outreq.Close = false diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index 20c4e16bcb..9153508ef4 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -664,3 +664,30 @@ func TestReverseProxy_CopyBuffer(t *testing.T) { } } } + +type staticTransport struct { + res *http.Response +} + +func (t *staticTransport) RoundTrip(r *http.Request) (*http.Response, error) { + return t.res, nil +} + +func BenchmarkServeHTTP(b *testing.B) { + res := &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(strings.NewReader("")), + } + proxy := &ReverseProxy{ + Director: func(*http.Request) {}, + Transport: &staticTransport{res}, + } + + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + + b.ReportAllocs() + for i := 0; i < b.N; i++ { + proxy.ServeHTTP(w, r) + } +}