ZhangZhihui's Blog  

Problem: You want to measure the lapsed time and make sure that it is accurate.


Solution: Use the monotonic clock in the Time struct to find the lapsed time.

 

The Time struct contains the data but only under certain circumstances. If you create a Time struct instance using time.Now , and print out the struct, you will be able to see the monotonic clock:

t := time.Now() 
fmt.Println(t)

When you run it you see this:

2023-10-24 18:54:04.771816477 +0800 CST m=+0.000021017

The m=+0.000021017 part is the monotonic clock. The part before that is the wall clock. This is what the package documentation says:
If the time has a monotonic clock reading, the returned string includes a final field “m=±<value>”, where value is the monotonic clock reading formatted as a decimal number of seconds.
But what does it mean by the monotonic clock reading formatted as a decimal number of seconds ? It’s a really small number! Actually, this just shows how long your program has been running.

 

func main() {
    time.Sleep(10 * time.Second) //  pretend  to  do  something  for  10s
    t1 := time.Now()
    t2 := time.Now()
    fmt.Println("t1:", t1)
    fmt.Println("t2:", t2)
    fmt.Println("difference:", t2.Sub(t1))
}

This is what you should see after 10 seconds:

zzh@ZZHPC:/zdata/MyPrograms/Go/study$ go run main.go
t1: 2023-10-24 18:59:01.682946905 +0800 CST m=+10.007175697
t2: 2023-10-24 18:59:01.682946973 +0800 CST m=+10.007175764
difference: 67ns

The interesting point to note here is that if you use the wall clock, you won’t be able to tell the difference at all!

As noted earlier, the monotonic clock data is not always available in the Time struct. Methods such as AddDate , Round , and Truncate are wall clock computations so the Time structs they return won’t have the monotonic clock. Similarly, In, Local , and UTC interpret the wall clock, so the Time structs they return won’t have the monotonic clock either.

You can also remove the monotonic clock yourself. Just use the Round method with a 0 parameter:

func main() {
    t := time.Now().Round(0)
    fmt.Println(t)
}

You should get something like this:

zzh@ZZHPC:/zdata/MyPrograms/Go/study$ go run main.go
2023-10-24 19:02:01.311982287 +0800 CST

You no longer see the monotonic clock here. So what happens when you try to call Sub (or any other monotonic methods) on a Time struct instance that doesn’t have the monotonic clock?

func main() {
    t1r := time.Now().Round(0)
    t2r := time.Now().Round(0)
    t3r := time.Now().Round(time.Second)
    t4r := time.Now().Round(time.Second)
    t1t := time.Now().Truncate(0)
    t2t := time.Now().Truncate(0)
    t3t := time.Now().Truncate(time.Second)
    t4t := time.Now().Truncate(time.Second)
    t5t := time.Now().Truncate(time.Millisecond)
    t6t := time.Now().Truncate(time.Millisecond)
    t7t := time.Now().Truncate(time.Microsecond)
    t8t := time.Now().Truncate(time.Microsecond)
    t9t := time.Now().Truncate(time.Nanosecond)
    t10t := time.Now().Truncate(time.Nanosecond)
    fmt.Println("t1r:", t1r)
    fmt.Println("t2r:", t2r)
    fmt.Println("t3r:", t3r)
    fmt.Println("t4r:", t4r)
    fmt.Println("t1t:", t1t)
    fmt.Println("t2t:", t2t)
    fmt.Println("t3t:", t3t)
    fmt.Println("t4t:", t4t)
    fmt.Println("t5t:", t5t)
    fmt.Println("t6t:", t6t)
    fmt.Println("t7t:", t7t)
    fmt.Println("t8t:", t8t)
    fmt.Println("t9t:", t9t)
    fmt.Println("t10t:", t10t)
    fmt.Println("difference between t1t and t2t:", t2t.Sub(t1t))
    fmt.Println("difference between t3t and t4t:", t4t.Sub(t3t))
    fmt.Println("difference between t5t and t6t:", t6t.Sub(t5t))
    fmt.Println("difference between t7t and t8t:", t8t.Sub(t7t))
    fmt.Println("difference between t9t and t10t:", t10t.Sub(t9t))
}

Now t1 and t2 have their monotonic clocks stripped away. If you try to find the difference between these two times, you will get a big fat 0. This is because the operation will be done on the wall clock instead of the monotonic clock, and the wall clock just isn’t fine-grained enough:

zzh@ZZHPC:/zdata/Github/ztest$ go run main.go
t1r: 2024-03-10 21:03:38.833227187 +0800 CST
t2r: 2024-03-10 21:03:38.833227258 +0800 CST
t3r: 2024-03-10 21:03:39 +0800 CST
t4r: 2024-03-10 21:03:39 +0800 CST
t1t: 2024-03-10 21:03:38.833227667 +0800 CST
t2t: 2024-03-10 21:03:38.833227729 +0800 CST
t3t: 2024-03-10 21:03:38 +0800 CST
t4t: 2024-03-10 21:03:38 +0800 CST
t5t: 2024-03-10 21:03:38.833 +0800 CST
t6t: 2024-03-10 21:03:38.833 +0800 CST
t7t: 2024-03-10 21:03:38.833228 +0800 CST
t8t: 2024-03-10 21:03:38.833228 +0800 CST
t9t: 2024-03-10 21:03:38.833228194 +0800 CST
t10t: 2024-03-10 21:03:38.833228252 +0800 CST
difference between t1t and t2t: 62ns
difference between t3t and t4t: 0s
difference between t5t and t6t: 0s
difference between t7t and t8t: 0s
difference between t9t and t10t: 58ns

 

posted on 2023-10-06 12:22  ZhangZhihuiAAA  阅读(4)  评论(0编辑  收藏  举报