]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: reuse textproto.Readers; remove 2 more allocations
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 28 Mar 2013 21:51:21 +0000 (14:51 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 28 Mar 2013 21:51:21 +0000 (14:51 -0700)
Saves both the textproto.Reader allocation, and its internal
scratch buffer growing.

benchmark                                   old ns/op    new ns/op    delta
BenchmarkServerFakeConnWithKeepAliveLite        10324        10149   -1.70%

benchmark                                  old allocs   new allocs    delta
BenchmarkServerFakeConnWithKeepAliveLite           19           17  -10.53%

benchmark                                   old bytes    new bytes    delta
BenchmarkServerFakeConnWithKeepAliveLite         1559         1492   -4.30%

R=golang-dev, r, gri
CC=golang-dev
https://golang.org/cl/8094046

src/pkg/net/http/request.go

index b42cc58a495c20b7f29be3f32f8005650a60de42..c1f862aadd6a93ddd15b3b7f51eec02adbd8cbb0 100644 (file)
@@ -478,10 +478,31 @@ func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
        return line[:s1], line[s1+1 : s2], line[s2+1:], true
 }
 
+// TODO(bradfitz): use a sync.Cache when available
+var textprotoReaderCache = make(chan *textproto.Reader, 4)
+
+func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
+       select {
+       case r := <-textprotoReaderCache:
+               r.R = br
+               return r
+       default:
+               return textproto.NewReader(br)
+       }
+}
+
+func putTextprotoReader(r *textproto.Reader) {
+       r.R = nil
+       select {
+       case textprotoReaderCache <- r:
+       default:
+       }
+}
+
 // ReadRequest reads and parses a request from b.
 func ReadRequest(b *bufio.Reader) (req *Request, err error) {
 
-       tp := textproto.NewReader(b)
+       tp := newTextprotoReader(b)
        req = new(Request)
 
        // First line: GET /index.html HTTP/1.0
@@ -490,6 +511,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
                return nil, err
        }
        defer func() {
+               putTextprotoReader(tp)
                if err == io.EOF {
                        err = io.ErrUnexpectedEOF
                }