Skip to content

Commit

Permalink
Keep idle connections in a channel rather than a slice
Browse files Browse the repository at this point in the history
This speeds up concurrent tests by 10%, while slightly decreasing
single process performance.
  • Loading branch information
fiam committed Oct 28, 2013
1 parent b29a9d6 commit ddfc51a
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions memcache/memcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,10 @@ func New(server ...string) *Client {

// NewFromSelector returns a new Client using the provided ServerSelector.
func NewFromSelector(ss ServerSelector) *Client {
return &Client{selector: ss}
return &Client{
selector: ss,
freeconn: make(map[string]chan *conn),
}
}

// Client is a memcache client.
Expand All @@ -212,8 +215,8 @@ type Client struct {

selector ServerSelector

lk sync.Mutex
freeconn map[string][]*conn
mu sync.RWMutex
freeconn map[string]chan *conn
}

// Item is an item to be got or stored in a memcached server.
Expand Down Expand Up @@ -275,32 +278,36 @@ func (cn *conn) condClose(err *error) {
}

func (c *Client) putFreeConn(addr net.Addr, cn *conn) {
c.lk.Lock()
defer c.lk.Unlock()
if c.freeconn == nil {
c.freeconn = make(map[string][]*conn)
}
c.mu.RLock()
freelist := c.freeconn[addr.String()]
if len(freelist) >= maxIdleConnsPerAddr {
c.mu.RUnlock()
if freelist == nil {
freelist = make(chan *conn, maxIdleConnsPerAddr)
c.mu.Lock()
c.freeconn[addr.String()] = freelist
c.mu.Unlock()
}
select {
case freelist <- cn:
break
default:
cn.nc.Close()
return
}
c.freeconn[addr.String()] = append(freelist, cn)
}

func (c *Client) getFreeConn(addr net.Addr) (cn *conn, ok bool) {
c.lk.Lock()
defer c.lk.Unlock()
if c.freeconn == nil {
c.mu.RLock()
freelist := c.freeconn[addr.String()]
c.mu.RUnlock()
if freelist == nil {
return nil, false
}
freelist, ok := c.freeconn[addr.String()]
if !ok || len(freelist) == 0 {
select {
case cn := <-freelist:
return cn, true
default:
return nil, false
}
cn = freelist[len(freelist)-1]
c.freeconn[addr.String()] = freelist[:len(freelist)-1]
return cn, true
}

func (c *Client) netTimeout() time.Duration {
Expand Down

0 comments on commit ddfc51a

Please sign in to comment.