From 7c60f0a43ffc6241730e4d69f769ede91edd5c57 Mon Sep 17 00:00:00 2001 From: Wang Xu Date: Thu, 25 Jan 2018 14:06:45 +0800 Subject: [PATCH 1/2] make the releaser simpler Because the acquire and recycle are done at the tail of array, the head is always the oldest unused socket. Signed-off-by: Wang Xu --- server.go | 73 ++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/server.go b/server.go index 2ae4ebbe3..1780ddcf4 100644 --- a/server.go +++ b/server.go @@ -80,14 +80,14 @@ var defaultServerInfo mongoServerInfo func newServer(addr string, tcpaddr *net.TCPAddr, sync chan bool, dial dialer, minPoolSize int, maxIdleTimeMS int) *mongoServer { server := &mongoServer{ - Addr: addr, - ResolvedAddr: tcpaddr.String(), - tcpaddr: tcpaddr, - sync: sync, - dial: dial, - info: &defaultServerInfo, - pingValue: time.Hour, // Push it back before an actual ping. - minPoolSize: minPoolSize, + Addr: addr, + ResolvedAddr: tcpaddr.String(), + tcpaddr: tcpaddr, + sync: sync, + dial: dial, + info: &defaultServerInfo, + pingValue: time.Hour, // Push it back before an actual ping. + minPoolSize: minPoolSize, maxIdleTimeMS: maxIdleTimeMS, } go server.pinger(true) @@ -217,8 +217,8 @@ func (server *mongoServer) RecycleSocket(socket *mongoSocket) { if !server.closed { now := time.Now() server.unusedSockets = append(server.unusedSockets, &timedMongoSocket{ - lastTimeUsed:&now, - soc:socket, + lastTimeUsed: &now, + soc: socket, }) } server.Unlock() @@ -358,44 +358,39 @@ func (server *mongoServer) pinger(loop bool) { } func (server *mongoServer) releaser() { - for { - - time.Sleep(1 * time.Minute) + ticker := time.NewTicker(1 * time.Minute) + for _ = range ticker.C { if server.closed { + ticker.Stop() return } - server.RLock() - if len(server.unusedSockets) < server.minPoolSize { - server.RUnlock() + server.Lock() + unused := len(server.unusedSockets) + if unused < server.minPoolSize { + server.Unlock() continue } - tmpSlice := make([]*timedMongoSocket, 0, len(server.unusedSockets) - server.minPoolSize) - for _, s := range server.unusedSockets { - if len(tmpSlice) == cap(tmpSlice) { + now := time.Now() + end := 0 + // Because the acquirision and recycle are done at the tail of array, + // the head is always the oldest unused socket. + for _, s := range server.unusedSockets[:unused-server.minPoolSize] { + if s.lastTimeUsed.Add(time.Duration(server.maxIdleTimeMS) * time.Millisecond).After(now) { break } - if time.Since(*(s.lastTimeUsed)) > time.Duration(server.maxIdleTimeMS) * time.Millisecond { - tmpSlice = append(tmpSlice, s) - } + end++ + } + tbr := server.unusedSockets[:end] + if end > 0 { + next := make([]*timedMongoSocket, unused-end) + copy(next, server.unusedSockets[end:]) + server.unusedSockets = next + stats.conn(-1*end, server.info.Master) } - server.RUnlock() + server.Unlock() - if len(tmpSlice) > 0 { - server.Lock() - for _, s := range tmpSlice { - for i, unused := range server.unusedSockets { - if s.soc == unused.soc { - copy(server.unusedSockets[i:], server.unusedSockets[i+1:]) - n := len(server.unusedSockets) - 1 - server.unusedSockets[n] = nil - server.unusedSockets = server.unusedSockets[:n] - stats.conn(-1, server.info.Master) - s.soc.Close() - break - } - } - } - server.Unlock() + for _, s := range tbr { + s.soc.Close() } } } From 1f9086f3ff79042e9aaa8d3df4c51747c2d3e2db Mon Sep 17 00:00:00 2001 From: Wang Xu Date: Thu, 25 Jan 2018 22:42:20 +0800 Subject: [PATCH 2/2] should release liveSockets as well when release unused Signed-off-by: Wang Xu --- server.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server.go b/server.go index 1780ddcf4..faf23ddb5 100644 --- a/server.go +++ b/server.go @@ -372,6 +372,7 @@ func (server *mongoServer) releaser() { } now := time.Now() end := 0 + reclaimMap := map[*mongoSocket]bool{} // Because the acquirision and recycle are done at the tail of array, // the head is always the oldest unused socket. for _, s := range server.unusedSockets[:unused-server.minPoolSize] { @@ -379,12 +380,20 @@ func (server *mongoServer) releaser() { break } end++ + reclaimMap[s.soc] = true } tbr := server.unusedSockets[:end] if end > 0 { next := make([]*timedMongoSocket, unused-end) copy(next, server.unusedSockets[end:]) server.unusedSockets = next + remainSockets := []*mongoSocket{} + for _, s := range server.liveSockets { + if !reclaimMap[s] { + remainSockets = append(remainSockets, s) + } + } + server.liveSockets = remainSockets stats.conn(-1*end, server.info.Master) } server.Unlock()