java System.nanoTime() 的精度与准确度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11452597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 05:10:33  来源:igfitidea点击:

Precision vs. accuracy of System.nanoTime()

javananotime

提问by andreasdr

The documentation for System.nanoTime()says the following (emphasis mine).

的文档System.nanoTime()说明如下(强调我的)。

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy.No guarantees are made about how frequently values change.

此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示自某个固定但任意的时间以来的纳秒(可能在未来,因此值可能为负)。此方法提供纳秒精度,但不一定提供纳秒精度。不保证值的更改频率。

As I see it, this can be interpreted in two different ways:

在我看来,这可以用两种不同的方式来解释:

  1. The sentence in boldabove refers to individual return values. Then, precision and accuracy are to be understood in the numerical sense. That is, precision refers to the number of significant digits - the position of truncation, and accuracy is whether the number is the correct one (such as described in the top answer here What is the difference between 'precision' and 'accuracy'?)

  2. The sentence in boldabove refers to the capability of the method itself. Then, precision and accuracy are to be understood as illustrated by the dartboard analogy ( http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy). So, low accuracy, high precision => the wrong value is repeatedly hit with a high precision: imagining that physical time stands still, consecutive calls of nanoTime() returns the same numerical value, but it is off from the actual elapsed time since the reference time by some constantoffset.

  1. 上面加粗的句子是指单个返回值。然后,精确度和准确度应从数字意义上来理解。也就是说,精度是指有效数字的位数——截断的位置,精度是数字是否正确(例如这里的顶级答案中描述的 '精度'和'准确度'有什么区别?

  2. 上面加粗的句子指的是方法本身的能力。然后,精度和准确度将被理解为飞镖板类比(http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy)。因此,低精度,高精度 => 以高精度重复命中错误值:假设物理时间静止不动,连续调用 nanoTime() 返回相同的数值,但它与实际经过的时间相距参考时间由一些恒定的偏移量。

Which interpretation is the correct one? My point is, interpretation 2 would mean that a measure of time differenceusing nanoTime() (by subtracting two return values) would be correct to the nanosecond (since the constant error/offset in the measurement would be eliminated), while interpretation 1 wouldn't guarantee that kind of compliance between measurements and thus wouldn't necessarily imply a high precision of time difference measurements.

哪种解释是正确的?我的观点是,解释 2 意味着使用 nanoTime()(通过减去两个返回值)对时间的测量将正确到纳秒(因为测量中的恒定误差/偏移将被消除),而解释 1 将不能保证测量之间的这种一致性,因此不一定意味着时间差测量的高精度。



Updated 4/15/13:The Java 7 documentation for System.nanoTime()has been updated to address the possible confusion with the previous wording.

2013 年4 月 15 日更新:Java 7 文档System.nanoTime()已更新,以解决可能与之前的措辞混淆的问题。

Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds.

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary origintime (perhaps in the future, so values may be negative). The same origin is used by all invocations of this method in an instance of a Java virtual machine; other virtual machine instances are likely to use a different origin.

This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().

Differences in successive calls that span greater than approximately 292 years (263nanoseconds) will not correctly compute elapsed time due to numerical overflow.

The values returned by this method become meaningful only when the difference between two such values, obtained within the same instance of a Java virtual machine, is computed.

返回正在运行的 Java 虚拟机的高分辨率时间源的当前值,以纳秒为单位。

此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示自某个固定但任意的原始时间以来的纳秒(可能在未来,因此值可能为负)。在 Java 虚拟机的实例中,此方法的所有调用都使用相同的来源;其他虚拟机实例可能使用不同的来源。

此方法提供纳秒精度,但不一定提供纳秒分辨率(即值更改的频率)- 除了分辨率至少与currentTimeMillis().

由于数值溢出,跨度超过大约 292 年(2 63纳秒)的连续调用的差异将无法正确计算经过的时间。

仅当计算在 Java 虚拟机的同一实例中获得的两个此类值之间的差异时,此方法返回的值才有意义。

采纳答案by Marko Topolnik

The first interpretation is correct. On most systems the three least-significant digits will always be zero. This in effect gives microsecond accuracy, but reports it at the fixed precision level of a nanosecond.

第一种解释是正确的。在大多数系统上,三个最低有效数字将始终为零。这实际上提供了微秒精度,但以纳秒的固定精度级别报告它。

In fact, now that I look at it again, your second interpretation is also a valid description of what is going on, maybe even more so. Imagining freezed time, the report will be always the same wrong number of nanoseconds, but correct if understood as the integer number of microseconds.

事实上,现在我再看一遍,你的第二个解释也是对正在发生的事情的有效描述,甚至可能更是如此。想象冻结时间,报告总是相同的错误的纳秒数,但如果理解为整数微秒数则正确。

回答by Joonas Pulakka

In Clojure command line, I get:

在 Clojure 命令行中,我得到:

user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
-641
user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
-642
user=> (- (System/nanoTime) (System/nanoTime))
-641
user=> (- (System/nanoTime) (System/nanoTime))
-641

So essentially, nanoTimedoesn't get updated every nanosecond, contrary to what one might intuitively expect from its precision. In Windows systems, it's using the QueryPerformanceCounterAPI under the hood (according to this article), which in practice seems to give about 640 ns resolution(in my system!).

所以本质上,nanoTime它不会每纳秒更新一次,这与人们可能直观地期望它的precision相反。在 Windows 系统中,它QueryPerformanceCounter在幕后使用 API(根据本文),实际上它似乎提供了大约 640 ns 的分辨率(在我的系统中!)。

Note that nanoTimecan't, by itself, have any accuracyat all, since its absolute value is arbitrary. Only the differencebetween successive nanoTimecalls is meaningful. The (in)accuracy of that difference is in the ballpark of 1 microsecond.

请注意,nanoTime它本身根本没有任何准确性,因为它的绝对值是任意的。只有 连续调用之间的差异nanoTime才有意义。该差异的(不)精度在 1 微秒的范围内。

回答by Ian Johnson

One quite interesting feature of the difference between System.currentTimeMillis()& System.nanoTime()is that System.nanoTime()does NOT change with the wall clock. I run code on a Windows virtual machine that has heavy time drift. System.currentTimeMillis()can jump back or forward by 1-2 seconds each time as NTP corrects that drift, making accurate time stamps meaningless. (Windows 2003, 2008 VPS editions)

System.currentTimeMillis()&之间的区别的一个非常有趣的特征System.nanoTime()是它System.nanoTime()不会随着挂钟而改变。我在时间漂移很大的 Windows 虚拟机上运行代码。System.currentTimeMillis()当 NTP 纠正漂移时,每次可以向后或向前跳跃 1-2 秒,使准确的时间戳变得毫无意义。(Windows 2003、2008 VPS 版本)

System.nanoTime()is not, however, affected by changing wall clock time so you can take a time retrieved over NTP and apply a correction based on System.nanoTime()since NTP was checked last and you have a far more accurate time than System.currentTimeMillis()in adverse wall clock conditions

System.nanoTime()但是,不会受到更改挂钟时间的影响,因此您可以通过 NTP 检索时间并根据System.nanoTime()上次检查NTP 后应用更正,并且您的时间比System.currentTimeMillis()不利的挂钟条件要准确得多

This is of course counter-intuitive, but useful to know

这当然是违反直觉的,但了解它很有用

回答by Eugene

If someone like me comes and reads this question again and again and againto still kind of understand it, here is a simpler (I hope) explanation.

如果有人像我一样来了,一遍又一遍读了这个问题,并再次给还是那样理解的,这里是一个简单的(我希望)的解释。

Precisionis about how many digits you retain. Each of the:

Precision是关于你保留了多少位数。每一个:

long start = System.nanoTime();
long end   = System.nanoTime();

is going to be a precise number (lots of digits).

将是一个精确的数字(很多数字)。

Since accuracyis measured only compared to something, an individual call to System.nanoTimemakes no sense since it's value is quite arbitrary and does not depend on something that we can measure. The only way to distinguish it's accuracy is to two different calls of it, thus:

由于accuracy与 something 进行比较,因此单独调用System.nanoTime没有任何意义,因为它的值是非常随意的,并且不依赖于我们可以测量的东西。区分它的准确性的唯一方法是对它的两个不同调用,因此:

 long howMuch = end - start;

is notgoing to have a nano-second accuracy. And in fact on my machine the difference is 0.2 - 0.3 micro-seconds.

不是将有一个纳米秒的精确度。事实上,在我的机器上,差异是 0.2 - 0.3 微秒。