From f2ddaffc31d94ffb7ac4c0f9d19adf2fbc96bd71 Mon Sep 17 00:00:00 2001 From: Erik Dubbelboer Date: Fri, 17 Aug 2018 17:15:41 +0800 Subject: [PATCH] Remove CoarseTime It is not clear why @valyala introduced this coarse time. Benchmarks on different systems show that the speedup is no where enough to justify the added code complexity and bugs it seems to have introduced. Mac: BenchmarkCoarseTimeNow-8 2000000000 2.49 ns/op 0 B/op 0 allocs/op BenchmarkTimeNow-8 500000000 3.14 ns/op 0 B/op 0 allocs/op Ubuntu: BenchmarkCoarseTimeNow-4 300000000 6.74 ns/op 0 B/op 0 allocs/op BenchmarkTimeNow-4 100000000 15.9 ns/op 0 B/op 0 allocs/op This reverts commit https://github.com/erikdubbelboer/fasthttp/commit/6309f42188ecb28ccf8ac58442739cdb43d75d9e and https://github.com/erikdubbelboer/fasthttp/commit/32c72cde80f0c591604f825586d6a4bbbb39d9c5. See: https://github.com/valyala/fasthttp/issues/271, https://github.com/valyala/fasthttp/pull/269 and https://github.com/valyala/fasthttp/issues/261. --- client.go | 14 +++++++------- coarseTime.go | 28 ---------------------------- coarseTime_test.go | 37 ------------------------------------- server.go | 21 ++++++++------------- workerpool.go | 2 +- 5 files changed, 16 insertions(+), 86 deletions(-) delete mode 100644 coarseTime.go delete mode 100644 coarseTime_test.go diff --git a/client.go b/client.go index fc11102a08..f74ad0cb0e 100644 --- a/client.go +++ b/client.go @@ -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(time.Now().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 := time.Now() 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 := time.Now() 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 = time.Now() 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 = time.Now() c.connsLock.Lock() c.conns = append(c.conns, cc) c.connsLock.Unlock() @@ -1991,7 +1991,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 := time.Now() if currentTime.Sub(lastWriteDeadlineTime) > (writeTimeout >> 2) { if err = conn.SetWriteDeadline(currentTime.Add(writeTimeout)); err != nil { w.err = err @@ -2072,7 +2072,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 := time.Now() 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 deleted file mode 100644 index 03c14f39a8..0000000000 --- a/coarseTime.go +++ /dev/null @@ -1,28 +0,0 @@ -package fasthttp - -import ( - "sync/atomic" - "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().Truncate(time.Second) - coarseTime.Store(&t) - go func() { - for { - time.Sleep(time.Second) - t := time.Now().Truncate(time.Second) - coarseTime.Store(&t) - } - }() -} - -var coarseTime atomic.Value diff --git a/coarseTime_test.go b/coarseTime_test.go deleted file mode 100644 index b2f2334ee3..0000000000 --- a/coarseTime_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package fasthttp - -import ( - "sync/atomic" - "testing" - "time" -) - -func BenchmarkCoarseTimeNow(b *testing.B) { - var zeroTimeCount uint64 - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - t := CoarseTimeNow() - if t.IsZero() { - atomic.AddUint64(&zeroTimeCount, 1) - } - } - }) - if zeroTimeCount > 0 { - b.Fatalf("zeroTimeCount must be zero") - } -} - -func BenchmarkTimeNow(b *testing.B) { - var zeroTimeCount uint64 - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - t := time.Now() - if t.IsZero() { - atomic.AddUint64(&zeroTimeCount, 1) - } - } - }) - if zeroTimeCount > 0 { - b.Fatalf("zeroTimeCount must be zero") - } -} diff --git a/server.go b/server.go index 689d91e804..4066d7b4b1 100644 --- a/server.go +++ b/server.go @@ -598,18 +598,13 @@ func (ctx *RequestCtx) ConnID() uint64 { return ctx.connID } -// Time returns RequestHandler call time truncated to the nearest second. -// -// Call time.Now() at the beginning of RequestHandler in order to obtain -// precise RequestHandler call time. +// Time returns 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 } @@ -1319,7 +1314,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 = time.Now() } // The current server reached concurrency limit, @@ -1361,7 +1356,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 = time.Now() } continue } @@ -1476,7 +1471,7 @@ func (s *Server) serveConn(c net.Conn) error { serverName := s.getServerName() connRequestNum := uint64(0) connID := nextConnID() - currentTime := CoarseTimeNow() + currentTime := time.Now() connTime := currentTime maxRequestBodySize := s.MaxRequestBodySize if maxRequestBodySize <= 0 { @@ -1533,7 +1528,7 @@ func (s *Server) serveConn(c net.Conn) error { } } - currentTime = CoarseTimeNow() + currentTime = time.Now() ctx.lastReadDuration = currentTime.Sub(ctx.time) if err != nil { @@ -1674,7 +1669,7 @@ func (s *Server) serveConn(c net.Conn) error { break } - currentTime = CoarseTimeNow() + currentTime = time.Now() } if br != nil { @@ -1730,7 +1725,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 := time.Now() 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)) @@ -1913,7 +1908,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 = time.Now() ctx.time = ctx.connTime keepBodyBuffer := !reduceMemoryUsage diff --git a/workerpool.go b/workerpool.go index cf602e0507..081ac65c39 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 = time.Now() wp.lock.Lock() if wp.mustStop { wp.lock.Unlock()