@@ -18,6 +18,35 @@ import (
1818
1919var noDeadline = time.Time {}
2020
21+ // Global time cache updated every 50ms by background goroutine.
22+ // This avoids expensive time.Now() syscalls in hot paths like getEffectiveReadTimeout.
23+ // Max staleness: 50ms, which is acceptable for timeout deadline checks (timeouts are typically 3-30 seconds).
24+ var globalTimeCache struct {
25+ nowNs atomic.Int64
26+ }
27+
28+ func init () {
29+ // Initialize immediately
30+ globalTimeCache .nowNs .Store (time .Now ().UnixNano ())
31+
32+ // Start background updater
33+ go func () {
34+ ticker := time .NewTicker (50 * time .Millisecond )
35+ defer ticker .Stop ()
36+
37+ for range ticker .C {
38+ globalTimeCache .nowNs .Store (time .Now ().UnixNano ())
39+ }
40+ }()
41+ }
42+
43+ // getCachedTimeNs returns the current time in nanoseconds from the global cache.
44+ // This is updated every 50ms by a background goroutine, avoiding expensive syscalls.
45+ // Max staleness: 50ms.
46+ func getCachedTimeNs () int64 {
47+ return globalTimeCache .nowNs .Load ()
48+ }
49+
2150// Global atomic counter for connection IDs
2251var connIDCounter uint64
2352
@@ -458,7 +487,8 @@ func (cn *Conn) getEffectiveReadTimeout(normalTimeout time.Duration) time.Durati
458487 return time .Duration (readTimeoutNs )
459488 }
460489
461- nowNs := time .Now ().UnixNano ()
490+ // Use cached time to avoid expensive syscall (max 50ms staleness is acceptable for timeout checks)
491+ nowNs := getCachedTimeNs ()
462492 // Check if deadline has passed
463493 if nowNs < deadlineNs {
464494 // Deadline is in the future, use relaxed timeout
@@ -491,7 +521,8 @@ func (cn *Conn) getEffectiveWriteTimeout(normalTimeout time.Duration) time.Durat
491521 return time .Duration (writeTimeoutNs )
492522 }
493523
494- nowNs := time .Now ().UnixNano ()
524+ // Use cached time to avoid expensive syscall (max 50ms staleness is acceptable for timeout checks)
525+ nowNs := getCachedTimeNs ()
495526 // Check if deadline has passed
496527 if nowNs < deadlineNs {
497528 // Deadline is in the future, use relaxed timeout
@@ -843,8 +874,10 @@ func (cn *Conn) MaybeHasData() bool {
843874
844875// deadline computes the effective deadline time based on context and timeout.
845876// It updates the usedAt timestamp to now.
877+ // Uses cached time to avoid expensive syscall (max 50ms staleness is acceptable for deadline calculation).
846878func (cn * Conn ) deadline (ctx context.Context , timeout time.Duration ) time.Time {
847- tm := time .Now ()
879+ // Use cached time for deadline calculation (called 2x per command: read + write)
880+ tm := time .Unix (0 , getCachedTimeNs ())
848881 cn .SetUsedAt (tm )
849882
850883 if timeout > 0 {
0 commit comments