golang墙上时钟与单调时钟如何实现

今天小编给大家分享一下golang墙上时钟与单调时钟如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧

今天小编给大家分享一下golang墙上时钟与单调时钟如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    墙上时钟与单调时钟

    墙上时钟

    墙上时钟也称为墙上时间。大多是1970年1月1日(UTC)以来的秒数和毫秒数。

    墙上时间可以和NTP(Network Time Protocal,网络时间协议)同步,但是如果本地时钟远远快于NTP服务器,则强制重置之后会跳到先前某个时间点。(这里不是很确定,猜测是如果时间差的不多,则调整石英晶体振荡器的频率,慢慢一致。如果差很多,则强行一致)

    单调时钟

    机器大多有自己的石英晶体振荡器,并将其作为计时器。单调时钟的绝对值没有任何意义,根据操作系统和语言的不同,单调时钟可能在程序开始时设为0、或在计算机启动后设为0等等。但是通过比较同一台计算机上两次单调时钟的差,可以获得相对准确的时间间隔。

    Time的结构

     type Time struct {
        // wall and ext encode the wall time seconds, wall time nanoseconds,
        // and optional monotonic clock reading in nanoseconds.
        //
        // From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),
        // a 33-bit seconds field, and a 30-bit wall time nanoseconds field.
        // The nanoseconds field is in the range [0, 999999999].
        // If the hasMonotonic bit is 0, then the 33-bit field must be zero
        // and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.
        // If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit
        // unsigned wall seconds since Jan 1 year 1885, and ext holds a
        // signed 64-bit monotonic clock reading, nanoseconds since process start.
        wall uint64
        ext  int64
        ...
     }

    wall和ext共同记录了时间,但是分为两种情况,一种是没有记录单调时钟(比如是通过字符串解析得到的时间),另一种是记录了单调时钟(比如通过Now)。

    wall的第一位是一个标记位

    如果为1,则表示记录了单调时钟。则wall的2-34(闭区间)位记录了从1885-1-1到现在的秒数,最后30位记录了纳秒数。而ext记录了从程序开始运行到现在经过的单调时钟数。

    如果为0,则表示没有记录单调时钟。则wall的2-34(闭区间)位全部为0(那最后30位是啥?)。而ext记录了从1-1-1到现在经过的秒数。

    Since的实现

    golang墙上时钟与单调时钟如何实现

    这里比较关键的代码是第914行的runtimeNano() - startNanostartNano的含义还是直接上代码比较明了。

     var startNano = 0
     
     func init(){
         startNano = runtimeNano()
     }

    runtimeNano()是调用了汇编,获取了操作系统当前的单调时钟。前面说过,单调时钟的绝对值没有什么意义。因此这里将两个时间相减,得到了从程序开始到现在的单调时钟。

    然后看一下Sub

     func (t Time) Sub(u Time) Duration {
        if t.wall&u.wall&hasMonotonic != 0 {
           te := t.ext
           ue := u.ext
           d := Duration(te - ue)
           if d < 0 && te > ue {
              return maxDuration // t - u is positive out of range
           }
           if d > 0 && te < ue {
              return minDuration // t - u is negative out of range
           }
           return d
        }
        d := Duration(t.sec()-u.sec())*Second + Duration(t.nsec()-u.nsec())
        // Check for overflow or underflow.
        switch {
        case u.Add(d).Equal(t):
           return d // d is correct
        case t.Before(u):
           return minDuration // t - u is negative out of range
        default:
           return maxDuration // t - u is positive out of range
        }
     }

    这里我们只需要关注2-13行即可。除去了范围检查,这里的主要逻辑就是两个Time的ext相减。而ext又都代表了单调时钟,所以最后返回的是单调时钟的差值。

    以上就是“golang墙上时钟与单调时钟如何实现”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注恰卡网行业资讯频道。

    本站部分文章来自网络或用户投稿,如无特殊说明或标注,均为本站原创发布。涉及资源下载的,本站旨在共享仅供大家学习与参考,如您想商用请获取官网版权,如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
    开发者

    怎么利用Anaconda创建虚拟环境

    2022-7-23 1:16:16

    开发者

    MySQL池化自定义实例分析

    2022-7-23 1:16:23

    搜索