Home >Backend Development >Golang >Monotonic clock processing of time package

Monotonic clock processing of time package

Golang菜鸟
Golang菜鸟forward
2023-08-04 17:45:081314browse

Today we are mainly going to take a look at the time application method of golang time package.

When it comes to computer processing clocks, there are two main ways:

  • Wall clock (wall time)
  • Monotonic clocks

The general rule between the two is that "wall time" is used for telling time, while "monotonic clock" is used forMeasure time; In addition, there are other clock processing methods.

If you still don’t understand the concepts of the above two clocks, then I recommend that you visit: Do you really understand the computer time? [1]This article details the origins of these two clocks.

Before reading the following, I will assume that you already know what a Wall Clock and a Monotone Clock are.

I will next look at an introduction to time.Time (translated by machine):

Time represents a time instant with nanosecond precision.

Programs that use times should generally store and pass them as values ​​rather than pointers. In other words, the type of time variables and structure fields should be time.Time, not *time.Time.

A Time value can be used by multiple goroutines at the same time, except GobDecode, UnmarshalBinary, The UnmarshalJSON and UnmarshalText methods are not concurrency safe.

Time instants can be compared using the Before, After, and Equal methods. The Sub method subtracts two instants, producing a duration. The Add method adds a duration to a time, producing a time.

The zero value of type Time is January 1, Year 1, 00:00:00.000000000 UTC. Since this time is unlikely to occur in practice, the IsZero method provides a simple way to detect times that have not been explicitly initialized.

Each Time is associated with a Location, which is referenced when calculating the representation of the time. For example in the Format, Hour and Year methods. The Local, UTC, and In methods return the time at a specific location. Changing the position in this way only changes the presentation; it does not change the moment of representation and therefore does not affect the calculations described in the previous paragraph.

The time value saved by the GobEncode, MarshalBinary, MarshalJSON, and MarshalText methods represents the offset at which the Time.Location is stored, but not the location name. Therefore, they lose information about daylight saving time.

In addition to the required "wall clock" reading, the time can also contain an optional reading of the current process's monotonic clock to provide additional comparison or subtraction precision. See the "Monotonic Clocks" section in the package documentation for details.

Note that the Go == operator compares not only time instants, but also positions and monotonic clock readings. Therefore, time values ​​should not be used as map or database keys without first ensuring that the same position has been set for all values, this can be achieved by using UTC or native methods, and that the monotonic clock reading has been stripped out setting t = t.Round(0). In general, prefer t.Equal(u) to t == u because t.Equal uses the most accurate comparison available and correctly handles the case where only one parameter has a monotonic clock reading.

This is the official introduction of time.TIme. Let's take a look at what the structure of Time looks like:

type Time struct {
 wall uint64
 ext  int64

 loc *Location
}

wall Its highest bit contains a 1-bit flag. Represents hasMonotonic, followed by 33 bits to track seconds; and finally 30 bits to track nanoseconds in the range [0, 999999999].

If the hasMonotonic bit is 0, the 33-bit field is zero, and ext stores the full signed 64-bit wall## since January 1, 2020 #Seconds.

如果该hasMonotonic位为1,则33位字段存储自1885年1月1日以来的无符号的wall秒数,而ext保留有符号的64位单调时钟读数,距离进程开始的时间为纳秒。这是大多数代码中通常发生的情况。

我们来通过 time.now() 函数来查看其中的区别:

// Now returns the current local time.
func Now() Time {
 sec, nsec, mono := now() // 返回对应的秒数,纳秒数,单调时钟数
 mono -= startNano
 sec += unixToInternal - minWall
 if uint64(sec)>>33 != 0 { // 判断如果秒数右移33位后大于0,说明不能采用单调时钟。
  return Time{uint64(nsec), sec + minWall, Local} // 按照 `wall` 时钟返回
 }
  
  // 返回 `wall` 时钟和 `monotonic` 时钟信息
 return Time{hasMonotonic | uint64(sec)<<nsecShift | uint64(nsec), mono, Local}
}

通过这个例子我们可以看到在time包中对于时间差的计算基本都会采用单调时钟墙上时钟的兼容。

  • func (t Time) After(u Time) bool {...}
  • func (t Time) Before(u Time) bool {...}
  • func (t Time) Equal(u Time) bool {...}
  • func (t Time) Add(d Duration) Time {...}
  • func (t Time) Sub(u Time) Duration {...}
  • func Since(t Time) Duration {...}
  • func Until(t Time) Duration {...}

对于增加修改时间计算会清除单调时钟,因为后面调用的是 unixTime 函数:

func unixTime(sec int64, nsec int32) Time {
 return Time{uint64(nsec), sec + unixToInternal, Local}
}

不会计算单调时钟的秒数,如下:

  • func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {...}
  • func Unix(sec int64, nsec int64) Time {...}
  • func UnixMilli(sec int64, nsec int64) Time {...}
  • func UnixMicro(sec int64, nsec int64) Time {...}
  • func (t Time) AddDate(years int, months int, days int) Time { ...}

I hope that after reading these concepts and knowledge, you will become more proficient in using the time package.

The above is the detailed content of Monotonic clock processing of time package. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:Golang菜鸟. If there is any infringement, please contact admin@php.cn delete