From e3915210aa7dfaff49af07821e65b214c80de229 Mon Sep 17 00:00:00 2001 From: yusing Date: Sat, 1 Nov 2025 02:18:24 +0800 Subject: [PATCH] fix(time): data race in DefaultTimeNow --- internal/utils/time_now.go | 12 +++++++----- internal/utils/time_now_test.go | 6 ++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/internal/utils/time_now.go b/internal/utils/time_now.go index 2426f8ff..d33aa91d 100644 --- a/internal/utils/time_now.go +++ b/internal/utils/time_now.go @@ -10,7 +10,7 @@ var ( TimeNow = DefaultTimeNow shouldCallTimeNow atomic.Bool timeNowTicker = time.NewTicker(shouldCallTimeNowInterval) - lastTimeNow = time.Now() + lastTimeNow = atomic.NewTime(time.Now()) ) const shouldCallTimeNowInterval = 100 * time.Millisecond @@ -26,11 +26,13 @@ func MockTimeNow(t time.Time) { // // Returned value may have +-100ms error. func DefaultTimeNow() time.Time { - if shouldCallTimeNow.Load() { - lastTimeNow = time.Now() - shouldCallTimeNow.Store(false) + swapped := shouldCallTimeNow.CompareAndSwap(false, true) + if swapped { // first call + now := time.Now() + lastTimeNow.Store(now) + return now } - return lastTimeNow + return lastTimeNow.Load() } func init() { diff --git a/internal/utils/time_now_test.go b/internal/utils/time_now_test.go index f2ddf549..3607c16f 100644 --- a/internal/utils/time_now_test.go +++ b/internal/utils/time_now_test.go @@ -5,16 +5,18 @@ import ( "time" ) +var sink time.Time + func BenchmarkTimeNow(b *testing.B) { b.Run("default", func(b *testing.B) { for b.Loop() { - time.Now() + sink = time.Now() } }) b.Run("reduced_call", func(b *testing.B) { for b.Loop() { - DefaultTimeNow() + sink = DefaultTimeNow() } }) }