System.nanoTime() はまったく役に立たないのでしょうか? 質問する

System.nanoTime() はまったく役に立たないのでしょうか? 質問する

ブログ記事に記載されているようにJava の System.nanoTime() に注意してくださいx86システムでは、JavaのSystem.nanoTime()は、CPU特定のカウンター。ここで、通話時間を測定するために使用する次のケースを考えてみましょう。

long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;

マルチコアシステムでは、time1を計測した後、スレッドが前のCPUよりも小さいカウンタを持つ別のプロセッサにスケジュールされる可能性があります。そのため、time2で次の値が得られます。少ないしたがって、timeSpent には負の値が返されます。

このケースを考えると、System.nanotime は今のところほとんど役に立たないのではないでしょうか?

システム時間を変更してもナノタイムには影響しないことはわかっています。これは、上で説明した問題ではありません。問題は、各 CPU がオンになってから異なるカウンターを保持することです。このカウンターは、最初の CPU と比較して 2 番目の CPU で低くなる可能性があります。スレッドは、time1 を取得した後、OS によって 2 番目の CPU にスケジュールされる可能性があるため、timeSpent の値は不正確で、負の値になることもあります。

ベストアンサー1

この回答は、当時のオペレーティング システムで実行されていた当時の Sun JDK が実際に何をしていたかという観点から 2011 年に書かれました。それはずいぶん昔のことです。レヴェントフの答えより最新の視点を提供します。

その投稿は間違っていますが、nanoTime安全です。投稿にリンクするコメントがありますデビッド・ホームズのブログ投稿、Sun のリアルタイムおよび並行処理担当者。そこにはこう書かれています。

System.nanoTime() は、QueryPerformanceCounter/QueryPerformanceFrequency API を使用して実装されます [...] QPC が使用するデフォルトのメカニズムは、ハードウェア抽象化レイヤー (HAL) によって決定されます [...] このデフォルトは、ハードウェア間だけでなく、OS バージョン間でも変わります。たとえば、Windows XP Service Pack 2 では、プロセッサ タイムスタンプ カウンター (TSC) ではなく、電源管理タイマー (PMTimer) を使用するように変更されました。これは、SMP システムの異なるプロセッサ間で TSC が同期されないという問題と、電源管理設定に基づいてその周波数 (したがって経過時間との関係) が変化する可能性があるためです。

つまり、Windowsでは、だったWinXP SP2 までは問題でしたが、今は問題ではありません。

他のプラットフォームについて言及しているパートII(またはそれ以上)は見つかりませんでしたが、その記事にはLinuxでも同じ問題に遭遇し、同じ方法で解決したというコメントが含まれており、clock_gettime(CLOCK_REALTIME) に関する FAQそこにはこう書かれています。

  1. clock_gettime(CLOCK_REALTIME) はすべてのプロセッサ/コアで一貫していますか? (アーキテクチャは重要ですか? 例: ppc、arm、x86、amd64、sparc)。

それすべきまたはバグがあると見なされます。

ただし、x86/x86_64 では、同期されていない TSC や可変周波数の TSC によって時間の不一致が発生する可能性があります。2.4 カーネルにはこれに対する保護機能がなく、初期の 2.6 カーネルでもこの​​点はうまく機能しませんでした。2.6.18 以降では、これを検出するためのロジックが改善され、通常は安全なクロックソースにフォールバックします。

ppc は常に同期されたタイムベースを持っているので、問題にはなりません。

nanoTimeしたがって、Holmes のリンクが を呼び出すことを意味していると解釈できる場合clock_gettime(CLOCK_REALTIME)、x86 のカーネル 2.6.18 以降ではほぼ安全であり、PowerPC でも常に安全です (IBM と Motorola は、Intel とは異なり、実際にマイクロプロセッサの設計方法を知っているため)。

残念ながら、SPARC や Solaris については何も言及されていません。そしてもちろん、IBM JVM が何を行うのかはわかりません。しかし、最新の Windows および Linux 上の Sun JVM はこれを正しく実行します。

編集:この回答は引用元に基づいています。しかし、実際には完全に間違っているのではないかと心配しています。より最新の情報があれば本当に助かります。私はちょうどLinuxのクロックに関する4年前の新しい記事それは役に立つかもしれません。

おすすめ記事