Skip to content

Commit d84b34a

Browse files
committed
address pr comments
1 parent 9e24679 commit d84b34a

File tree

4 files changed

+81
-23
lines changed

4 files changed

+81
-23
lines changed

internal/pool/conn.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,6 @@ var (
2727
errConnNotAvailableForWrite = errors.New("redis: connection not available for write operation")
2828
)
2929

30-
// Global time cache updated every 50ms by background goroutine.
31-
// This avoids expensive time.Now() syscalls in hot paths like getEffectiveReadTimeout.
32-
// Max staleness: 50ms, which is acceptable for timeout deadline checks (timeouts are typically 3-30 seconds).
33-
var globalTimeCache struct {
34-
nowNs atomic.Int64
35-
}
36-
37-
func init() {
38-
// Initialize immediately
39-
globalTimeCache.nowNs.Store(time.Now().UnixNano())
40-
41-
// Start background updater
42-
go func() {
43-
ticker := time.NewTicker(50 * time.Millisecond)
44-
defer ticker.Stop()
45-
46-
for range ticker.C {
47-
globalTimeCache.nowNs.Store(time.Now().UnixNano())
48-
}
49-
}()
50-
}
51-
5230
// getCachedTimeNs returns the current time in nanoseconds from the global cache.
5331
// This is updated every 50ms by a background goroutine, avoiding expensive syscalls.
5432
// Max staleness: 50ms.

internal/pool/global_time_cache.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package pool
2+
3+
import (
4+
"sync"
5+
"sync/atomic"
6+
"time"
7+
)
8+
9+
// Global time cache updated every 50ms by background goroutine.
10+
// This avoids expensive time.Now() syscalls in hot paths like getEffectiveReadTimeout.
11+
// Max staleness: 50ms, which is acceptable for timeout deadline checks (timeouts are typically 3-30 seconds).
12+
var globalTimeCache struct {
13+
nowNs atomic.Int64
14+
lock sync.Mutex
15+
started bool
16+
stop chan struct{}
17+
subscribers int32
18+
}
19+
20+
func subscribeToGlobalTimeCache() {
21+
globalTimeCache.lock.Lock()
22+
globalTimeCache.subscribers += 1
23+
globalTimeCache.lock.Unlock()
24+
}
25+
26+
func unsubscribeFromGlobalTimeCache() {
27+
globalTimeCache.lock.Lock()
28+
globalTimeCache.subscribers -= 1
29+
globalTimeCache.lock.Unlock()
30+
}
31+
32+
func startGlobalTimeCache() {
33+
globalTimeCache.lock.Lock()
34+
if globalTimeCache.started {
35+
globalTimeCache.lock.Unlock()
36+
return
37+
}
38+
39+
globalTimeCache.started = true
40+
globalTimeCache.nowNs.Store(time.Now().UnixNano())
41+
globalTimeCache.stop = make(chan struct{})
42+
globalTimeCache.lock.Unlock()
43+
// Start background updater
44+
go func() {
45+
ticker := time.NewTicker(50 * time.Millisecond)
46+
defer ticker.Stop()
47+
48+
for range ticker.C {
49+
select {
50+
case <-globalTimeCache.stop:
51+
return
52+
default:
53+
}
54+
globalTimeCache.nowNs.Store(time.Now().UnixNano())
55+
}
56+
}()
57+
}
58+
59+
// stopGlobalTimeCache stops the global time cache if there are no subscribers.
60+
// This should only be called when the last subscriber is removed.
61+
func stopGlobalTimeCache() {
62+
globalTimeCache.lock.Lock()
63+
if !globalTimeCache.started || globalTimeCache.subscribers > 0 {
64+
globalTimeCache.lock.Unlock()
65+
return
66+
}
67+
globalTimeCache.started = false
68+
close(globalTimeCache.stop)
69+
globalTimeCache.lock.Unlock()
70+
}
71+
72+
func init() {
73+
startGlobalTimeCache()
74+
}

internal/pool/pool.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ func NewConnPool(opt *Options) *ConnPool {
177177
p.connsMu.Unlock()
178178
}
179179

180+
startGlobalTimeCache()
181+
subscribeToGlobalTimeCache()
182+
180183
return p
181184
}
182185

@@ -959,6 +962,9 @@ func (p *ConnPool) Close() error {
959962
return ErrClosed
960963
}
961964

965+
unsubscribeFromGlobalTimeCache()
966+
stopGlobalTimeCache()
967+
962968
var firstErr error
963969
p.connsMu.Lock()
964970
for _, cn := range p.conns {

redis.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ func (c *Conn) TxPipeline() Pipeliner {
13531353

13541354
// processPushNotifications processes all pending push notifications on a connection
13551355
// This ensures that cluster topology changes are handled immediately before the connection is used
1356-
// This method should be called by the client before using WithWriter for command execution
1356+
// This method should be called by the client before using WithReader for command execution
13571357
//
13581358
// Performance optimization: Skip the expensive MaybeHasData() syscall if a health check
13591359
// was performed recently (within 5 seconds). The health check already verified the connection

0 commit comments

Comments
 (0)