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.
This commit is contained in:
Erik Dubbelboer
2018-08-17 17:15:41 +08:00
parent 4a16377d6e
commit f2ddaffc31
5 changed files with 16 additions and 86 deletions
+7 -7
View File
@@ -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
-28
View File
@@ -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
-37
View File
@@ -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")
}
}
+8 -13
View File
@@ -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
+1 -1
View File
@@ -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()