Skip to content

Commit

Permalink
快速时钟增加获取 nanos 的函数
Browse files Browse the repository at this point in the history
  • Loading branch information
FishGoddess committed Aug 7, 2024
1 parent 2ed3cc8 commit b9532ba
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## ✒ 历史版本的特性介绍 (Features in old versions)

### v1.8.1

> 此版本发布于 2024-08-07
* 快速时钟增加获取 nanos 的函数

### v1.8.0

> 此版本发布于 2024-08-07
Expand Down
4 changes: 2 additions & 2 deletions _icons/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 18 additions & 8 deletions extension/fastclock/fast_clock.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ import (
// In my linux server with 2 cores:
// BenchmarkTimeNow-2 19150246 62.26 ns/op 0 B/op 0 allocs/op
// BenchmarkFastClockNow-2 357209233 3.46 ns/op 0 B/op 0 allocs/op
// BenchmarkFastClockNowNanos-2 467461363 2.55 ns/op 0 B/op 0 allocs/op
//
// However, the performance of time.Now is faster enough for 99.9% situations, so we hope you never use it :)
type fastClock struct {
nowNanos int64
nanos int64
}

func newClock() *fastClock {
clock := &fastClock{
nowNanos: time.Now().UnixNano(),
nanos: time.Now().UnixNano(),
}

go clock.start()
Expand All @@ -49,17 +50,16 @@ func (fc *fastClock) start() {
for {
for i := 0; i < 9; i++ {
time.Sleep(duration)
atomic.AddInt64(&fc.nowNanos, int64(duration))
atomic.AddInt64(&fc.nanos, int64(duration))
}

time.Sleep(duration)
atomic.StoreInt64(&fc.nowNanos, time.Now().UnixNano())
atomic.StoreInt64(&fc.nanos, time.Now().UnixNano())
}
}

func (fc *fastClock) now() time.Time {
nanos := atomic.LoadInt64(&fc.nowNanos)
return time.Unix(0, nanos)
func (fc *fastClock) Nanos() int64 {
return atomic.LoadInt64(&fc.nanos)
}

var (
Expand All @@ -73,5 +73,15 @@ func Now() time.Time {
clock = newClock()
})

return clock.now()
nanos := NowNanos()
return time.Unix(0, nanos)
}

// NowNanos returns the current time in nanos from fast clock.
func NowNanos() int64 {
clockOnce.Do(func() {
clock = newClock()
})

return clock.Nanos()
}
28 changes: 28 additions & 0 deletions extension/fastclock/fast_clock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ func BenchmarkFastClockNow(b *testing.B) {
}
}

// go test -v -run=^$ -bench=^BenchmarkFastClockNowNanos$ -benchtime=1s
func BenchmarkFastClockNowNanos(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
NowNanos()
}
}

// go test -v -cover -count=1 -test.cpu=1 -run=^TestNow$
func TestNow(t *testing.T) {
duration := 100 * time.Millisecond
Expand All @@ -57,3 +67,21 @@ func TestNow(t *testing.T) {
time.Sleep(time.Duration(rand.Int63n(int64(duration))))
}
}

// go test -v -cover -count=1 -test.cpu=1 -run=^TestNowNanos$
func TestNowNanos(t *testing.T) {
duration := 100 * time.Millisecond

for i := 0; i < 100; i++ {
gotNanos := NowNanos()
got := time.Unix(0, gotNanos)
gap := time.Since(got)
t.Logf("got: %v, gap: %v", got, gap)

if math.Abs(float64(gap.Nanoseconds())) > float64(duration)*1.1 {
t.Errorf("now %v is wrong", got)
}

time.Sleep(time.Duration(rand.Int63n(int64(duration))))
}
}

0 comments on commit b9532ba

Please sign in to comment.