diff --git a/pipe.go b/pipe.go index 97ae6d82..de852a91 100644 --- a/pipe.go +++ b/pipe.go @@ -286,6 +286,7 @@ func (p *pipe) _backgroundWrite() (err error) { ones = make([]cmds.Completed, 1) multi []cmds.Completed ch chan RedisResult + delay = p.maxFlushDelay ) for atomic.LoadInt32(&p.state) < 3 { @@ -293,16 +294,12 @@ func (p *pipe) _backgroundWrite() (err error) { if p.w.Buffered() == 0 { err = p.Error() } else { - if p.maxFlushDelay == 0 { + if delay == 0 || atomic.LoadInt32(&p.waits) == 1 { // do not delay for sequential usage err = p.w.Flush() } else { - if atomic.LoadInt32(&p.waits) == 1 { - err = p.w.Flush() - } else { - ts := time.Now() - err = p.w.Flush() - time.Sleep(p.maxFlushDelay - time.Since(ts)) - } + ts := time.Now() + err = p.w.Flush() + time.Sleep(delay - time.Since(ts)) // ref: https://github.com/rueian/rueidis/issues/156 } } if err == nil { diff --git a/rueidis.go b/rueidis.go index 51b62385..8ac168eb 100644 --- a/rueidis.go +++ b/rueidis.go @@ -110,6 +110,15 @@ type ClientOption struct { // This default is ClientOption.Dialer.KeepAlive * (9+1), where 9 is the default of tcp_keepalive_probes on Linux. ConnWriteTimeout time.Duration + // MaxFlushDelay when greater than zero pauses pipeline write loop for some time (not larger than MaxFlushDelay) + // after each flushing of data to the connection. This gives pipeline a chance to collect more commands to send + // to Redis. Adding this delay increases latency, reduces throughput – but in most cases may significantly reduce + // application and Redis CPU utilization due to less executed system calls. By default, Rueidis flushes data to the + // connection without extra delays. Depending on network latency and application-specific conditions the value + // of MaxFlushDelay may vary, sth like 20 microseconds should not affect latency/throughput a lot but still + // produce notable CPU usage reduction under load. Ref: https://github.com/rueian/rueidis/issues/156 + MaxFlushDelay time.Duration + // ShuffleInit is a handy flag that shuffles the InitAddress after passing to the NewClient() if it is true ShuffleInit bool // DisableRetry disables retrying read-only commands under network errors @@ -118,14 +127,6 @@ type ClientOption struct { DisableCache bool // AlwaysPipelining makes rueidis.Client always pipeline redis commands even if they are not issued concurrently. AlwaysPipelining bool - // MaxFlushDelay when greater than zero pauses pipeline write loop for some time (not larger than MaxFlushDelay) - // after each flushing of data to the connection. This gives pipeline a chance to collect more commands to send - // to Redis. Adding this delay increases latency, reduces throughput – but in most cases may significantly reduce - // application and Redis CPU utilization due to less executed system calls. By default, Rueidis flushes data to the - // connection without extra delays. Depending on network latency and application-specific conditions the value - // of MaxFlushDelay may vary, sth like 20 microseconds should not affect latency/throughput a lot but still - // produce notable CPU usage reduction under load. - MaxFlushDelay time.Duration } // SentinelOption contains MasterSet,