1
0
mirror of https://github.com/golang/go synced 2024-10-03 05:21:22 -06:00

net/http: reuse textproto.Readers; remove 2 more allocations

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
This commit is contained in:
Brad Fitzpatrick 2013-03-28 14:51:21 -07:00
parent f1b7c140ff
commit 1b0d04b89f

View 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 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. // ReadRequest reads and parses a request from b.
func ReadRequest(b *bufio.Reader) (req *Request, err error) { func ReadRequest(b *bufio.Reader) (req *Request, err error) {
tp := textproto.NewReader(b) tp := newTextprotoReader(b)
req = new(Request) req = new(Request)
// First line: GET /index.html HTTP/1.0 // First line: GET /index.html HTTP/1.0
@ -490,6 +511,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
return nil, err return nil, err
} }
defer func() { defer func() {
putTextprotoReader(tp)
if err == io.EOF { if err == io.EOF {
err = io.ErrUnexpectedEOF err = io.ErrUnexpectedEOF
} }