diff options
author | Aliaksandr Valialkin <valyala@gmail.com> | 2017-02-10 15:45:14 +0200 |
---|---|---|
committer | Aliaksandr Valialkin <valyala@gmail.com> | 2017-02-10 15:45:14 +0200 |
commit | 32c72cde80f0c591604f825586d6a4bbbb39d9c5 (patch) | |
tree | 2fd80906166fb4b6ff21233fb7e07df7f24532db | |
parent | optimization: substitute time.Now() calls with coarse-grained time in hot paths (diff) | |
download | fasthttp-32c72cde80f0c591604f825586d6a4bbbb39d9c5.tar.gz fasthttp-32c72cde80f0c591604f825586d6a4bbbb39d9c5.tar.bz2 fasthttp-32c72cde80f0c591604f825586d6a4bbbb39d9c5.zip |
Export CoarseTimeNow and clarify that RequestCtx.Time() and RequestCtx.ConnTime() return time truncated to a second
-rw-r--r-- | client.go | 14 | ||||
-rw-r--r-- | coarseTime.go | 9 | ||||
-rw-r--r-- | coarseTime_test.go | 2 | ||||
-rw-r--r-- | server.go | 21 | ||||
-rw-r--r-- | workerpool.go | 2 |
5 files changed, 28 insertions, 20 deletions
@@ -1041,7 +1041,7 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error) panic("BUG: resp cannot be nil") } - atomic.StoreUint32(&c.lastUseTime, uint32(coarseTimeNow().Unix()-startTimeUnix)) + atomic.StoreUint32(&c.lastUseTime, uint32(CoarseTimeNow().Unix()-startTimeUnix)) // Free up resources occupied by response before sending the request, // so the GC may reclaim these resources (e.g. response body). @@ -1057,7 +1057,7 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error) // Optimization: update write deadline only if more than 25% // of the last write deadline exceeded. // See https://github.com/golang/go/issues/15133 for details. - currentTime := coarseTimeNow() + currentTime := CoarseTimeNow() if currentTime.Sub(cc.lastWriteDeadlineTime) > (c.WriteTimeout >> 2) { if err = conn.SetWriteDeadline(currentTime.Add(c.WriteTimeout)); err != nil { c.closeConn(cc) @@ -1101,7 +1101,7 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error) // Optimization: update read deadline only if more than 25% // of the last read deadline exceeded. // See https://github.com/golang/go/issues/15133 for details. - currentTime := coarseTimeNow() + currentTime := CoarseTimeNow() if currentTime.Sub(cc.lastReadDeadlineTime) > (c.ReadTimeout >> 2) { if err = conn.SetReadDeadline(currentTime.Add(c.ReadTimeout)); err != nil { c.closeConn(cc) @@ -1276,7 +1276,7 @@ func acquireClientConn(conn net.Conn) *clientConn { } cc := v.(*clientConn) cc.c = conn - cc.createdTime = coarseTimeNow() + cc.createdTime = CoarseTimeNow() return cc } @@ -1288,7 +1288,7 @@ func releaseClientConn(cc *clientConn) { var clientConnPool sync.Pool func (c *HostClient) releaseConn(cc *clientConn) { - cc.lastUseTime = coarseTimeNow() + cc.lastUseTime = CoarseTimeNow() c.connsLock.Lock() c.conns = append(c.conns, cc) c.connsLock.Unlock() @@ -1988,7 +1988,7 @@ func (c *pipelineConnClient) writer(conn net.Conn, stopCh <-chan struct{}) error // Optimization: update write deadline only if more than 25% // of the last write deadline exceeded. // See https://github.com/golang/go/issues/15133 for details. - currentTime := coarseTimeNow() + currentTime := CoarseTimeNow() if currentTime.Sub(lastWriteDeadlineTime) > (writeTimeout >> 2) { if err = conn.SetWriteDeadline(currentTime.Add(writeTimeout)); err != nil { w.err = err @@ -2069,7 +2069,7 @@ func (c *pipelineConnClient) reader(conn net.Conn, stopCh <-chan struct{}) error // Optimization: update read deadline only if more than 25% // of the last read deadline exceeded. // See https://github.com/golang/go/issues/15133 for details. - currentTime := coarseTimeNow() + currentTime := CoarseTimeNow() if currentTime.Sub(lastReadDeadlineTime) > (readTimeout >> 2) { if err = conn.SetReadDeadline(currentTime.Add(readTimeout)); err != nil { w.err = err diff --git a/coarseTime.go b/coarseTime.go index cb3f598..03c14f3 100644 --- a/coarseTime.go +++ b/coarseTime.go @@ -5,18 +5,21 @@ import ( "time" ) -func coarseTimeNow() time.Time { +// CoarseTimeNow returns the current time truncated to the nearest second. +// +// This is a faster alternative to time.Now(). +func CoarseTimeNow() time.Time { tp := coarseTime.Load().(*time.Time) return *tp } func init() { - t := time.Now() + t := time.Now().Truncate(time.Second) coarseTime.Store(&t) go func() { for { time.Sleep(time.Second) - t := time.Now() + t := time.Now().Truncate(time.Second) coarseTime.Store(&t) } }() diff --git a/coarseTime_test.go b/coarseTime_test.go index 15715c5..b2f2334 100644 --- a/coarseTime_test.go +++ b/coarseTime_test.go @@ -10,7 +10,7 @@ func BenchmarkCoarseTimeNow(b *testing.B) { var zeroTimeCount uint64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { - t := coarseTimeNow() + t := CoarseTimeNow() if t.IsZero() { atomic.AddUint64(&zeroTimeCount, 1) } @@ -592,13 +592,18 @@ func (ctx *RequestCtx) ConnID() uint64 { return ctx.connID } -// Time returns RequestHandler call time. +// Time returns RequestHandler call time truncated to the nearest second. +// +// Call time.Now() at the beginning of RequestHandler in order to obtain +// percise RequestHandler call time. func (ctx *RequestCtx) Time() time.Time { return ctx.time } // ConnTime returns the time server starts serving the connection // the current request came from. +// +// The returned time is truncated to the nearest second. func (ctx *RequestCtx) ConnTime() time.Time { return ctx.connTime } @@ -1280,7 +1285,7 @@ func (s *Server) Serve(ln net.Listener) error { if time.Since(lastOverflowErrorTime) > time.Minute { s.logger().Printf("The incoming connection cannot be served, because %d concurrent connections are served. "+ "Try increasing Server.Concurrency", maxWorkersCount) - lastOverflowErrorTime = coarseTimeNow() + lastOverflowErrorTime = CoarseTimeNow() } // The current server reached concurrency limit, @@ -1322,7 +1327,7 @@ func acceptConn(s *Server, ln net.Listener, lastPerIPErrorTime *time.Time) (net. if time.Since(*lastPerIPErrorTime) > time.Minute { s.logger().Printf("The number of connections from %s exceeds MaxConnsPerIP=%d", getConnIP4(c), s.MaxConnsPerIP) - *lastPerIPErrorTime = coarseTimeNow() + *lastPerIPErrorTime = CoarseTimeNow() } continue } @@ -1437,7 +1442,7 @@ func (s *Server) serveConn(c net.Conn) error { serverName := s.getServerName() connRequestNum := uint64(0) connID := nextConnID() - currentTime := coarseTimeNow() + currentTime := CoarseTimeNow() connTime := currentTime maxRequestBodySize := s.MaxRequestBodySize if maxRequestBodySize <= 0 { @@ -1494,7 +1499,7 @@ func (s *Server) serveConn(c net.Conn) error { } } - currentTime = coarseTimeNow() + currentTime = CoarseTimeNow() ctx.lastReadDuration = currentTime.Sub(ctx.time) if err != nil { @@ -1635,7 +1640,7 @@ func (s *Server) serveConn(c net.Conn) error { break } - currentTime = coarseTimeNow() + currentTime = CoarseTimeNow() } if br != nil { @@ -1691,7 +1696,7 @@ func (s *Server) updateWriteDeadline(c net.Conn, ctx *RequestCtx, lastDeadlineTi // Optimization: update write deadline only if more than 25% // of the last write deadline exceeded. // See https://github.com/golang/go/issues/15133 for details. - currentTime := coarseTimeNow() + currentTime := CoarseTimeNow() if currentTime.Sub(lastDeadlineTime) > (writeTimeout >> 2) { if err := c.SetWriteDeadline(currentTime.Add(writeTimeout)); err != nil { panic(fmt.Sprintf("BUG: error in SetWriteDeadline(%s): %s", writeTimeout, err)) @@ -1874,7 +1879,7 @@ func (ctx *RequestCtx) Init2(conn net.Conn, logger Logger, reduceMemoryUsage boo ctx.connID = nextConnID() ctx.s = fakeServer ctx.connRequestNum = 0 - ctx.connTime = coarseTimeNow() + ctx.connTime = CoarseTimeNow() ctx.time = ctx.connTime keepBodyBuffer := !reduceMemoryUsage diff --git a/workerpool.go b/workerpool.go index 1faee33..cf602e0 100644 --- a/workerpool.go +++ b/workerpool.go @@ -187,7 +187,7 @@ func (wp *workerPool) getCh() *workerChan { } func (wp *workerPool) release(ch *workerChan) bool { - ch.lastUseTime = coarseTimeNow() + ch.lastUseTime = CoarseTimeNow() wp.lock.Lock() if wp.mustStop { wp.lock.Unlock() |