1

なぜこのコード

    long s, e, sum1 = 0, sum2 = 0, TRIALS = 10000000;

    for(long i=0; i<TRIALS; i++) {
        s = System.nanoTime();
        e = System.nanoTime();
        sum1 += e - s;            
        s = System.nanoTime();
        e = System.nanoTime();
        sum2 += e - s;
    }        
    System.out.println(sum1 / TRIALS);
    System.out.println(sum2 / TRIALS);

この結果を生成します

-60  
61 

「私のマシンで?」

編集:
Sam I am's answerは、役立つ nanoSecond() ドキュメントを指していますが、より正確には、結果が一貫して最初の合計を支持するのはなぜですか?

「私のマシン」:
JavaSE-1.7、Eclipse
Win 7 x64、AMD Athlon II X4 635

ループ内で順番を入れ替えると逆の結果になる

for(int i=0; i<TRIALS; i++) {            
    s = System.nanoTime();
    e = System.nanoTime();
    sum2 += e - s;            
    s = System.nanoTime();
    e = System.nanoTime();
    sum1 += e - s;
}  
61
-61  

sum1 に追加する前に (es) を調べると、sum1 が正になります。

for(long i=0; i<TRIALS; i++) {
    s = System.nanoTime();
    e = System.nanoTime();
    temp = e-s;
    if(temp < 0)
        count++;
    sum1 += temp;

    s = System.nanoTime();
    e = System.nanoTime();
    sum2 += e - s;
}
61  
61

アンドリュー・アルコックが指摘するように、sum1 += -s + e は期待される結果を生成します。

for(long i=0; i<TRIALS; i++) {
    s = System.nanoTime();
    e = System.nanoTime();
    sum1 += -s + e;

    s = System.nanoTime();
    e = System.nanoTime();
    sum2 += -s + e;
}
61
61

その他のいくつかのテスト: http://pastebin.com/QJ93NZxP

4

3 に答える 3

2

この答えは仮定です。環境に関する詳細で質問を更新すると、他の誰かがより詳細で根拠のある回答を提供できる可能性があります。

このnanoTime()機能は、アクセス待ち時間が短い高解像度タイマーにアクセスすることで機能します。x86では、これがタイムスタンプカウンターであると思います。これは、マシンの基本的なクロックサイクルによって駆動されます。

+/- 60 nsの一貫した結果が表示されている場合は、マシンのタイマーの基本的な間隔が表示されているだけだと思います。

しかし、負の数はどうですか?繰り返しになりますが、ウィキペディアの記事を読むと、Intelプロセッサが命令を並べ替える可能性があるというコメントが表示されます。

于 2013-01-02T22:39:48.967 に答える
1

roundar と組み合わせて、このコードでいくつかのテストを実行しました。要約すると、次の場合に効果がなくなりました。

  1. インタープリター モード (-Xint) で同じコードを実行する
  2. 集計ロジックの順序を からに変更sum += e - sするsum += -s + e
  3. いくつかの異なるアーキテクチャまたは異なる VM で実行されている (たとえば、Mac で Java 6 を実行した)
  4. s と e を検査するログ ステートメントを配置する
  5. s と e で追加の演算を実行する

さらに、効果はスレッドではありません。

  1. 生成される追加のスレッドはありません
  2. ローカル変数のみが含まれます
  3. この効果は roundar の環境で 100% 再現可能であり、常に正確に同じタイミング、つまり +61 と -61 になります。

次の理由により、効果はタイミングの問題ではありません。

  1. 実行は 10m の反復で行われます
  2. この効果は roundar の環境で 100% 再現可能です。
  3. 結果は、すべての反復で正確に同じタイミング、つまり +61 と -61 になります。

以上のことから、Java VM の hotspot モジュールにバグがあると思います。書かれたコードは肯定的な結果を返すはずですが、そうではありません。

于 2013-01-03T10:07:44.170 に答える
0

オラクルのドキュメントから直接

つまり、値を更新する頻度によって、結果が異なる可能性があります。

ナノタイム

public static long nanoTime()

最も正確な使用可能なシステム タイマーの現在の値をナノ秒単位で返します。

このメソッドは、経過時間を測定するためにのみ使用でき、システム時間またはウォールクロック時間の他の概念とは関係ありません。

返される値は、固定された任意の時間からのナノ秒を表します (おそらく将来であるため、値は負の可能性があります)。この方法はナノ秒の精度を提供しますが、必ずしもナノ秒の精度ではありません。値が変更される頻度については保証されません。約 292 年 (263 ナノ秒) を超える連続する呼び出しの違いは、数値のオーバーフローのため、経過時間を正確に計算できません。

For example, to measure how long some code takes to execute:

   long startTime = System.nanoTime();
   // ... the code being measured ...
   long estimatedTime = System.nanoTime() - startTime;
 

Returns:
    The current value of the system timer, in nanoseconds.
Since:
    1.5
于 2013-01-02T22:23:32.667 に答える