[解決済み] System.nanoTime()は全く使えないのか?
質問
ブログ記事で紹介したように JavaにおけるSystem.nanoTime()の注意点 x86システムでは、JavaのSystem.nanoTime()は CPU のカウンタがあります。ここで、私が呼び出しの時間を測定するために使用する次のケースを考えてみましょう。
long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;
さて、マルチコアシステムでは、時間1を計測した後、スレッドは前のCPUのカウンタより小さい別のプロセッサにスケジューリングされる可能性があります。したがって、time2 の値は次のようになります。 少ない 時間1より したがって、timeSpentには負の値が入ることになります。
このケースを考えると、今のところSystem.nanotimeはかなり使い物にならないのではないでしょうか?
システム時刻を変更してもナノタイムに影響がないことは知っています。それは私が上で説明した問題ではありません。問題は、各CPUが電源を入れてから異なるカウンターを保持することです。このカウンターは、最初のCPUと比較して2番目のCPUでは低くなる可能性があります。スレッドはtime1を取得した後、OSによって2番目のCPUにスケジューリングされることがあるので、timeSpentの値は不正確で、マイナスになることもありえます。
解決方法は?
この回答は、2011年に、当時のOS上で動作する当時のSun JDKが実際に行っていたことの観点から書かれたものです。ずいぶん昔の話ですね。 レヴェントフさんの回答 は、より最新の視点を提供しています。
その投稿は間違いであり
nanoTime
が安全です。その投稿には、以下のようなコメントがあり、リンクしています。
David Holmesのブログ記事
Sunのリアルタイムと並行処理の専門家です。こう書いてある。
System.nanoTime() は QueryPerformanceCounter/QueryPerformanceFrequency API を使用して実装されています [...] QPC が使用するデフォルトメカニズムは Hardware Abstraction layer(HAL) によって決定されます [...] このデフォルトはハードウェアだけでなく OS バージョン間でも変更されています。たとえば、Windows XP Service Pack 2 では、プロセッサ タイムスタンプ カウンタ (TSC) ではなく、パワー マネジメント タイマ (PMTimer) を使用するように変更されました。これは、SMP システムの異なるプロセッサで TSC が同期されていない問題や、パワー マネジメント設定によってその周波数(つまり、経過時間との関係)が変化するためです。
つまり、Windowsでは、この でした WinXP SP2までは問題なかったのですが、今はありません。
他のプラットフォームについて書かれたパートII(以上)は見当たりませんが、その記事にはLinuxが同じ問題に遭遇し、同じように解決したという記述があり、そのリンク先として clock_gettime(CLOCK_REALTIME)に関するFAQです。 と書いてある。
- clock_gettime(CLOCK_REALTIME) は、すべてのプロセッサ/コアで一貫していますか?(アーキテクチャは重要ですか? 例: ppc, arm, x86, amd64, sparc).
それは すべき でないとバグとみなされる。
しかし、x86/x86_64 では、非同期または可変周波数の TSC が時間の不一致を引き起こすことがあります。2.4 カーネルはこれに対する防御が全くなく、初期の 2.6 カーネルもこの点ではあまりうまくいっていませんでした。2.6.18 以降では、これを検出するロジックが改善され、通常は安全なクロックソースにフォールバックするようになりました。
ppcは常にタイムベースが同期しているので、問題ないはずです。
つまり、ホームズのリンクは、次のことを意味していると読み取れるのです。
nanoTime
コール
clock_gettime(CLOCK_REALTIME)
というのは、IBM と Motorola は Intel と違って、マイクロプロセッサの設計を実際に知っているからです)。
SPARCやSolarisについては、残念ながら言及されていない。そしてもちろん、IBMのJVMが何をするのか見当もつかない。しかし、最新のWindowsとLinux上のSun JVMは、これを正しく実行しています。
編集部:この回答は、引用しているソースに基づいています。しかし、実際には完全に間違っているのではないかと、私はまだ心配しています。もっと最新の情報があれば、本当に貴重だと思います。私はちょうど Linuxのクロックに関する4年前の新しい記事 というのは便利かもしれません。
関連
-
スレッド "main "での例外をEclipseで解決 java.lang.Error: 未解決のコンパイル問題、コンパイラとパッケージの不整合
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
ファインバグタイプ
-
SpringBootApplication を型解決できない。
-
JQuery DataTable 详解
-
Methodのinvokeメソッド実装のJavaリフレクション
-
あるコードに出会いましたが、何に使うのか理解できません。 List<String> list = new ArrayList<String>() { { a
-
起動時にEclipseエラーが発生しました。起動中に内部エラーが発生しました。java.lang.NullPoin: "Javaツーリングの初期化 "中に内部エラーが発生しました。
-
[解決済み] 整数の平方根が整数であるかどうかを判断する最速の方法
-
[解決済み] System.currentTimeMillisとSystem.nanoTimeの比較
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Java Exceptionが発生しました エラー解決
-
アクセス制限です。タイプ 'Application' は API ではありません。
-
SpringBootApplication を型解決できない。
-
this()の呼び出しはコンストラクタ本体の最初の文でなければならない 例外解決と原因分析
-
Eclipseプロンプトを実行する java仮想マシンを使用しない
-
java.lang.NoClassDefFoundError: org.apache.jasper.el.ELContextImpl クラスを初期化できませんでした。
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました
-
Java(1)仕上げの基本概念+eclipseのインストール構成
-
[解決済み] System.currentTimeMillisとSystem.nanoTimeの比較
-
[解決済み] Javaで経過時間を計測するには?[重複しています]