web-dev-qa-db-ja.com

System.nanoTime()の精度と精度

System.nanoTime() のドキュメントには、次のように書かれています(私の強調)。

この方法は、経過時間を測定するためにのみ使用でき、システムや実時間のその他の概念とは関係ありません。返される値は、固定されているが任意の時間からのナノ秒を表します(おそらく将来的には、値が負になる可能性があります)。 この方法はナノ秒の精度を提供しますが、必ずしもナノ秒の精度である必要はありません。値が変更される頻度については保証されません。

私が見ているように、これは2つの異なる方法で解釈できます。

  1. 上記のboldの文は、個々の戻り値を示しています。次に、精度と精度を数値の意味で理解する必要があります。つまり、精度とは有効桁数(切り捨ての位置)を指し、精度は数値が正しいかどうかです(ここの一番上の回答で説明されているように 「精度」と「精度」の違いは何ですか? ?

  2. 上記のboldの文は、メソッド自体の機能を示しています。次に、ダーツボードのアナロジー( http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy )で示されているように、精度と精度を理解する必要があります。したがって、低精度、高精度=>間違った値が高精度で繰り返しヒットされます。物理時間が静止していると想像すると、nanoTime()を連続して呼び出すと同じ数値が返されますが、実際の経過時間とは異なります。いくつかの定数オフセットによる参照時間。

正しい解釈はどれですか?私のポイントは、解釈2は、nanoTime()を使用した時間の測定値(2つの戻り値を減算することによる)がナノ秒に正しいことを意味します(一定のエラー/オフセットのため)解釈1は、測定間のその種のコンプライアンスを保証するものではなく、したがって、必ずしも時間差測定の高精度を意味するわけではありません。


2013年4月15日更新:Java 7ドキュメント System.nanoTime() が更新され、前の文言と混同される可能性があります。

実行中のJava仮想マシンの高解像度タイムソースの現在の値をナノ秒単位で返します。

この方法は、経過時間を測定するためにのみ使用でき、システムや実時間のその他の概念とは関係ありません。返される値は、固定されているが任意のOrigin時間(おそらく将来、値が負になる可能性がある)からのナノ秒を表します。 Java仮想マシン;他の仮想マシンインスタンスは異なるオリジンを使用する可能性が高いため、このメソッドのすべての呼び出しで同じオリジンが使用されます。

この方法はナノ秒の精度を提供しますが、必ずしもナノ秒の解像度(つまり、値が変化する頻度)ではありません-解像度が少なくとも currentTimeMillis() の解像度と同じくらい良いことを除いて、保証は行われません。

約292年を超える連続通話の違い(263 ナノ秒)は、数値のオーバーフローのために経過時間を正しく計算しません。

このメソッドによって返される値は、Java仮想マシンの同じインスタンス内で取得された2つのそのような値の差が計算された場合にのみ意味があります。

24
andreasdr

最初の解釈は正しいです。ほとんどのシステムでは、最下位3桁は常にゼロになります。これは事実上マイクロ秒の精度を提供しますが、ナノ秒の固定精度レベルで報告します。

実際、もう一度見てみると、2番目の解釈も、何が起こっているのかについての有効な説明であり、おそらくもっとそうです。フリーズした時間を想像すると、レポートは常に同じ間違ったナノ秒数になりますが、マイクロ秒の整数として理解されれば正しいでしょう。

10
Marko Topolnik

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

したがって、本質的に、nanoTimeは、その精度から直感的に期待できるものとは異なり、ナノ秒ごとに更新されるわけではありません。 Windowsシステムでは、内部でQueryPerformanceCounter AP​​Iを使用しています( この記事 による)。これにより、実際には約640 nsの解像度が得られるようです。 (私のシステムでは!)。

nanoTimeは、その絶対値が任意であるため、それ自体では精度を持つことができないことに注意してください。連続するnanoTime呼び出し間のdifferenceのみが意味を持ちます。その違いの(不)正確さは、1マイクロ秒の球場にあります。

12
Joonas Pulakka

System.currentTimeMillis()System.nanoTime()の違いの非常に興味深い機能の1つは、System.nanoTime()が掛け時計によって変化しないことです。時間のずれが大きいWindows仮想マシンでコードを実行します。 System.currentTimeMillis()は、NTPがそのドリフトを修正し、正確なタイムスタンプを無意味にするため、毎回1〜2秒ずつ前後にジャンプできます。(Windows2003、2008 VPSエディション)

ただし、System.nanoTime()は実時間の変更による影響を受けないため、NTPで取得した時間を取り、System.nanoTime()に基づいて修正を適用できます。 NTPが最後にチェックされ、不利な壁時計条件でSystem.currentTimeMillis()よりもはるかに正確な時刻があります

これはもちろん直感に反しますが、知っておくと便利です

4
Ian Johnson

私のような誰かがこの質問を何度も何度も読んでいる場合そして何度もそれでも理解するために、ここにもっと簡単な(私は願っています)説明があります。

Precisionは、保持する桁数です。各々の:

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

正確な数(多くの桁)になります。

accuracy何かと比較してのみ測定されるため、_System.nanoTime_の個々の呼び出しは、その値が非常に任意であり、測定できるものに依存しないため、意味がありません。その精度を区別する唯一の方法は、2つの異なる呼び出しを行うことです。

_ long howMuch = end - start;
_

notナノ秒の精度になります。実際、私のマシンでは、その差は0.2〜0.3マイクロ秒です。

1
Eugene