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 (
"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
}
......
......@@ -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.
......
......@@ -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)
}
}
......
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