From: Brad Fitzpatrick Date: Wed, 18 Dec 2013 23:52:20 +0000 (-0800) Subject: net/http: use sync.Pool X-Git-Tag: go1.3beta1~1153 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=93e4a9d84c4d7c955c953523f5c88db7b46405a4;p=gostls13.git net/http: use sync.Pool Update #4720 R=golang-dev, iant CC=golang-dev https://golang.org/cl/44080043 --- diff --git a/src/pkg/net/http/header.go b/src/pkg/net/http/header.go index ca1ae07c25..de62bef552 100644 --- a/src/pkg/net/http/header.go +++ b/src/pkg/net/http/header.go @@ -9,6 +9,7 @@ import ( "net/textproto" "sort" "strings" + "sync" "time" ) @@ -114,18 +115,15 @@ func (s *headerSorter) Len() int { return len(s.kvs) } func (s *headerSorter) Swap(i, j int) { s.kvs[i], s.kvs[j] = s.kvs[j], s.kvs[i] } func (s *headerSorter) Less(i, j int) bool { return s.kvs[i].key < s.kvs[j].key } -// TODO: convert this to a sync.Cache (issue 4720) -var headerSorterCache = make(chan *headerSorter, 8) +var headerSorterPool = sync.Pool{ + New: func() interface{} { return new(headerSorter) }, +} // sortedKeyValues returns h's keys sorted in the returned kvs // slice. The headerSorter used to sort is also returned, for possible // return to headerSorterCache. func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) { - select { - case hs = <-headerSorterCache: - default: - hs = new(headerSorter) - } + hs = headerSorterPool.Get().(*headerSorter) if cap(hs.kvs) < len(h) { hs.kvs = make([]keyValues, 0, len(h)) } @@ -159,10 +157,7 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error { } } } - select { - case headerSorterCache <- sorter: - default: - } + headerSorterPool.Put(sorter) return nil } diff --git a/src/pkg/net/http/request.go b/src/pkg/net/http/request.go index 57b5d09484..7702d320c7 100644 --- a/src/pkg/net/http/request.go +++ b/src/pkg/net/http/request.go @@ -20,6 +20,7 @@ import ( "net/url" "strconv" "strings" + "sync" ) const ( @@ -494,25 +495,20 @@ 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) +var textprotoReaderPool sync.Pool func newTextprotoReader(br *bufio.Reader) *textproto.Reader { - select { - case r := <-textprotoReaderCache: - r.R = br - return r - default: - return textproto.NewReader(br) + if v := textprotoReaderPool.Get(); v != nil { + tr := v.(*textproto.Reader) + tr.R = br + return tr } + return textproto.NewReader(br) } func putTextprotoReader(r *textproto.Reader) { r.R = nil - select { - case textprotoReaderCache <- r: - default: - } + textprotoReaderPool.Put(r) } // ReadRequest reads and parses a request from b. diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go index 0e46863d5a..3b80d45fdd 100644 --- a/src/pkg/net/http/server.go +++ b/src/pkg/net/http/server.go @@ -435,56 +435,52 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) { return c, nil } -// TODO: use a sync.Cache instead var ( - bufioReaderCache = make(chan *bufio.Reader, 4) - bufioWriterCache2k = make(chan *bufio.Writer, 4) - bufioWriterCache4k = make(chan *bufio.Writer, 4) + bufioReaderPool sync.Pool + bufioWriter2kPool sync.Pool + bufioWriter4kPool sync.Pool ) -func bufioWriterCache(size int) chan *bufio.Writer { +func bufioWriterPool(size int) *sync.Pool { switch size { case 2 << 10: - return bufioWriterCache2k + return &bufioWriter2kPool case 4 << 10: - return bufioWriterCache4k + return &bufioWriter4kPool } return nil } func newBufioReader(r io.Reader) *bufio.Reader { - select { - case p := <-bufioReaderCache: - p.Reset(r) - return p - default: - return bufio.NewReader(r) + if v := bufioReaderPool.Get(); v != nil { + br := v.(*bufio.Reader) + br.Reset(r) + return br } + return bufio.NewReader(r) } func putBufioReader(br *bufio.Reader) { br.Reset(nil) - select { - case bufioReaderCache <- br: - default: - } + bufioReaderPool.Put(br) } func newBufioWriterSize(w io.Writer, size int) *bufio.Writer { - select { - case p := <-bufioWriterCache(size): - p.Reset(w) - return p - default: - return bufio.NewWriterSize(w, size) + pool := bufioWriterPool(size) + if pool != nil { + if v := pool.Get(); v != nil { + bw := v.(*bufio.Writer) + bw.Reset(w) + return bw + } } + return bufio.NewWriterSize(w, size) } func putBufioWriter(bw *bufio.Writer) { bw.Reset(nil) - select { - case bufioWriterCache(bw.Available()) <- bw: - default: + if pool := bufioWriterPool(bw.Available()); pool != nil { + pool.Put(bw) } }