22

Go 的 time 包声称可以提供纳秒级的精度。 http://golang.org/src/pkg/time/time.go

我想知道它是如何实现的,我是否可以信任它。我的疑虑来自 Python,它清楚地记录了它随着时间的推移而遇到的困难和局限性:

来自http://docs.python.org/2/library/time.html

各种实时函数的精度可能低于表达它们的值或参数的单位所建议的精度。例如,在大多数 Unix 系统上,时钟每秒只“滴答”50 或 100 次。

另一方面,time() 和 sleep() 的精度优于 Unix 等效项:时间以浮点数表示,time() 返回可用的最准确时间(在可用的情况下使用 Unix gettimeofday()),以及sleep() 将接受一个非零分数的时间(Unix select() 用于实现这一点,如果可用)。

既然操作系统给 python 带来了如此困难的时间,那么 Go 是如何实现其纳秒精度的呢?

4

3 回答 3

35

至于实现,time.Now()回退到运行时中实现的函数。您可以查看C 时间实现time·now汇编中的实现(在本例中为 linux amd64)。然后使用clock_gettime,它提供纳秒分辨率。在 Windows 上,这是通过调用 来实现的GetSystemTimeAsFileTime,它也会生成纳秒(不是高分辨率,而是纳秒)。

所以是的,分辨率取决于操作系统,你不能指望它在每个操作系统上都是准确的,但开发人员正在努力让它尽可能好。例如,在 go1.0.3 中,time·now对于 FreeBSD使用gettimeofday而不是clock_gettime,它只提供毫秒精度。您可以通过查看存储在 中的值来了解这一点AX,因为它是系统调用 ID。如果您查看引用的程序集,您可以看到 ms 值乘以 1000 以获得纳秒。但是,现在已解决。

如果您想确定,请检查运行时源代码中的相应实现并询问您的操作系统的手册。

于 2013-01-30T18:41:18.437 回答
16

Python 的time.time函数的问题之一是它返回一个float。浮点数是IEEE 754 双精度数,具有 53 位精度。

由于自 1970-01-01(纪元)以来已经超过 2**30 秒,您需要 61 (31 + 30) 位精度来存储自 1970-01-01 以来精确到纳秒的时间。

不幸的是,这比你可以存储在 python 浮点数中的内容少 7 或 8 位,这意味着 python 浮点数总是不如 go time 精确。

为了量化,下面的演示表明,python 时间最多精确到 100nS,只是由于float类型的限制。

>>> t = time()
>>> t
1359587524.591781
>>> t == t + 1E-6
False
>>> t == t + 1E-7
True

所以去吧,从int64nS 开始并计数没有这些限制,并且仅限于底层操作系统的精度,正如 nemo 很好地解释的那样。

于 2013-01-30T23:20:39.743 回答
0

如果您有兴趣查询操作系统以获取返回值的精度clock_gettime,您可以clock_getres使用适合您的操作系统的 syscall 包进行系统调用。例如,在 Unix 平台上,您可以执行以下操作:

package main

import (
    "fmt"
    "golang.org/x/sys/unix"
)

func main() {
    res := unix.Timespec{}
    unix.ClockGetres(unix.CLOCK_MONOTONIC, &res)
    fmt.Printf("Monotonic clock resolution is %d nanoseconds\n", res.Nsec)
}

时间包使用来自单调时钟的值进行比较和涉及时间的操作;挂钟时间的精度类似地通过unix.CLOCK_MONOTONIC在上面的示例中更改为 来获得unix.CLOCK_REALTIME

于 2020-11-28T18:52:39.227 回答