@@ -219,7 +219,7 @@ type Server struct {
219219
220220 concurrencyCh chan struct {}
221221
222- idleConns map [net.Conn ]time. Time
222+ idleConns map [net.Conn ]* atomic. Int64
223223 done chan struct {}
224224
225225 // Server name for sending in response headers.
@@ -2132,6 +2132,26 @@ func (s *Server) serveConn(c net.Conn) (err error) {
21322132 return handler (c )
21332133 }
21342134
2135+ s .idleConnsMu .Lock ()
2136+ if s .idleConns == nil {
2137+ s .idleConns = make (map [net.Conn ]* atomic.Int64 )
2138+ }
2139+ idleConnTime , ok := s .idleConns [c ]
2140+ if ! ok {
2141+ v := idleConnTimePool .Get ()
2142+ if v == nil {
2143+ v = & atomic.Int64 {}
2144+ }
2145+ idleConnTime = v .(* atomic.Int64 )
2146+ s .idleConns [c ] = idleConnTime
2147+ }
2148+
2149+ // Count the connection as Idle after 5 seconds.
2150+ // Same as net/http.Server:
2151+ // https://github.com/golang/go/blob/85d7bab91d9a3ed1f76842e4328973ea75efef54/src/net/http/server.go#L2834-L2836
2152+ idleConnTime .Store (time .Now ().Add (time .Second * 5 ).Unix ())
2153+ s .idleConnsMu .Unlock ()
2154+
21352155 serverName := s .getServerName ()
21362156 connRequestNum := uint64 (0 )
21372157 connID := nextConnID ()
@@ -2207,6 +2227,8 @@ func (s *Server) serveConn(c net.Conn) (err error) {
22072227 if err == nil {
22082228 s .setState (c , StateActive )
22092229
2230+ idleConnTime .Store (0 )
2231+
22102232 if s .ReadTimeout > 0 {
22112233 if err = c .SetReadDeadline (time .Now ().Add (s .ReadTimeout )); err != nil {
22122234 break
@@ -2485,6 +2507,8 @@ func (s *Server) serveConn(c net.Conn) (err error) {
24852507 err = nil
24862508 break
24872509 }
2510+
2511+ idleConnTime .Store (time .Now ().Unix ())
24882512 }
24892513
24902514 if br != nil {
@@ -2497,11 +2521,18 @@ func (s *Server) serveConn(c net.Conn) (err error) {
24972521 s .releaseCtx (ctx )
24982522 }
24992523
2524+ s .idleConnsMu .Lock ()
2525+ ic , ok := s .idleConns [c ]
2526+ if ok {
2527+ idleConnTimePool .Put (ic )
2528+ delete (s .idleConns , c )
2529+ }
2530+ s .idleConnsMu .Unlock ()
2531+
25002532 return
25012533}
25022534
25032535func (s * Server ) setState (nc net.Conn , state ConnState ) {
2504- s .trackConn (nc , state )
25052536 if hook := s .ConnState ; hook != nil {
25062537 hook (nc , state )
25072538 }
@@ -2878,36 +2909,17 @@ func (s *Server) writeErrorResponse(bw *bufio.Writer, ctx *RequestCtx, serverNam
28782909 return bw
28792910}
28802911
2881- func (s * Server ) trackConn (c net.Conn , state ConnState ) {
2882- s .idleConnsMu .Lock ()
2883- switch state {
2884- case StateIdle :
2885- if s .idleConns == nil {
2886- s .idleConns = make (map [net.Conn ]time.Time )
2887- }
2888- s .idleConns [c ] = time .Now ()
2889- case StateNew :
2890- if s .idleConns == nil {
2891- s .idleConns = make (map [net.Conn ]time.Time )
2892- }
2893- // Count the connection as Idle after 5 seconds.
2894- // Same as net/http.Server:
2895- // https://github.com/golang/go/blob/85d7bab91d9a3ed1f76842e4328973ea75efef54/src/net/http/server.go#L2834-L2836
2896- s .idleConns [c ] = time .Now ().Add (time .Second * 5 )
2897-
2898- default :
2899- delete (s .idleConns , c )
2900- }
2901- s .idleConnsMu .Unlock ()
2902- }
2912+ var idleConnTimePool sync.Pool
29032913
29042914func (s * Server ) closeIdleConns () {
29052915 s .idleConnsMu .Lock ()
2906- now := time .Now ()
2907- for c , t := range s .idleConns {
2908- if now .Sub (t ) >= 0 {
2916+ now := time .Now ().Unix ()
2917+ for c , ict := range s .idleConns {
2918+ t := ict .Load ()
2919+ if t != 0 && now - t >= 0 {
29092920 _ = c .Close ()
29102921 delete (s .idleConns , c )
2922+ idleConnTimePool .Put (ict )
29112923 }
29122924 }
29132925 s .idleConnsMu .Unlock ()
0 commit comments