Commit 93e4a9d8 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: use sync.Pool

Update #4720

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/44080043
parent 46b4ed2c
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"net/textproto" "net/textproto"
"sort" "sort"
"strings" "strings"
"sync"
"time" "time"
) )
...@@ -114,18 +115,15 @@ func (s *headerSorter) Len() int { return len(s.kvs) } ...@@ -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) 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 } 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 headerSorterPool = sync.Pool{
var headerSorterCache = make(chan *headerSorter, 8) New: func() interface{} { return new(headerSorter) },
}
// sortedKeyValues returns h's keys sorted in the returned kvs // sortedKeyValues returns h's keys sorted in the returned kvs
// slice. The headerSorter used to sort is also returned, for possible // slice. The headerSorter used to sort is also returned, for possible
// return to headerSorterCache. // return to headerSorterCache.
func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) { func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) {
select { hs = headerSorterPool.Get().(*headerSorter)
case hs = <-headerSorterCache:
default:
hs = new(headerSorter)
}
if cap(hs.kvs) < len(h) { if cap(hs.kvs) < len(h) {
hs.kvs = make([]keyValues, 0, 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 { ...@@ -159,10 +157,7 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
} }
} }
} }
select { headerSorterPool.Put(sorter)
case headerSorterCache <- sorter:
default:
}
return nil return nil
} }
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sync"
) )
const ( const (
...@@ -494,25 +495,20 @@ func parseRequestLine(line string) (method, requestURI, proto string, ok bool) { ...@@ -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 return line[:s1], line[s1+1 : s2], line[s2+1:], true
} }
// TODO(bradfitz): use a sync.Cache when available var textprotoReaderPool sync.Pool
var textprotoReaderCache = make(chan *textproto.Reader, 4)
func newTextprotoReader(br *bufio.Reader) *textproto.Reader { func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
select { if v := textprotoReaderPool.Get(); v != nil {
case r := <-textprotoReaderCache: tr := v.(*textproto.Reader)
r.R = br tr.R = br
return r return tr
default:
return textproto.NewReader(br)
} }
return textproto.NewReader(br)
} }
func putTextprotoReader(r *textproto.Reader) { func putTextprotoReader(r *textproto.Reader) {
r.R = nil r.R = nil
select { textprotoReaderPool.Put(r)
case textprotoReaderCache <- r:
default:
}
} }
// ReadRequest reads and parses a request from b. // ReadRequest reads and parses a request from b.
......
...@@ -435,56 +435,52 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) { ...@@ -435,56 +435,52 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
return c, nil return c, nil
} }
// TODO: use a sync.Cache instead
var ( var (
bufioReaderCache = make(chan *bufio.Reader, 4) bufioReaderPool sync.Pool
bufioWriterCache2k = make(chan *bufio.Writer, 4) bufioWriter2kPool sync.Pool
bufioWriterCache4k = make(chan *bufio.Writer, 4) bufioWriter4kPool sync.Pool
) )
func bufioWriterCache(size int) chan *bufio.Writer { func bufioWriterPool(size int) *sync.Pool {
switch size { switch size {
case 2 << 10: case 2 << 10:
return bufioWriterCache2k return &bufioWriter2kPool
case 4 << 10: case 4 << 10:
return bufioWriterCache4k return &bufioWriter4kPool
} }
return nil return nil
} }
func newBufioReader(r io.Reader) *bufio.Reader { func newBufioReader(r io.Reader) *bufio.Reader {
select { if v := bufioReaderPool.Get(); v != nil {
case p := <-bufioReaderCache: br := v.(*bufio.Reader)
p.Reset(r) br.Reset(r)
return p return br
default:
return bufio.NewReader(r)
} }
return bufio.NewReader(r)
} }
func putBufioReader(br *bufio.Reader) { func putBufioReader(br *bufio.Reader) {
br.Reset(nil) br.Reset(nil)
select { bufioReaderPool.Put(br)
case bufioReaderCache <- br:
default:
}
} }
func newBufioWriterSize(w io.Writer, size int) *bufio.Writer { func newBufioWriterSize(w io.Writer, size int) *bufio.Writer {
select { pool := bufioWriterPool(size)
case p := <-bufioWriterCache(size): if pool != nil {
p.Reset(w) if v := pool.Get(); v != nil {
return p bw := v.(*bufio.Writer)
default: bw.Reset(w)
return bufio.NewWriterSize(w, size) return bw
}
} }
return bufio.NewWriterSize(w, size)
} }
func putBufioWriter(bw *bufio.Writer) { func putBufioWriter(bw *bufio.Writer) {
bw.Reset(nil) bw.Reset(nil)
select { if pool := bufioWriterPool(bw.Available()); pool != nil {
case bufioWriterCache(bw.Available()) <- bw: pool.Put(bw)
default:
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment