2009-09-30 172 views
14

的Java可以訪問兩個方法來獲取當前時間:System.nanoTime()System.currentTimeMillis()。第一個以納秒爲單位給出結果,但實際的精度比那個要差很多(幾微秒)。精確的時間度量在Java中

JVM是否已經爲每臺特定機器提供了最佳可能值? 否則,是否有一些Java庫可以提供更好的度量,可能是通過綁定到特定的系統?

+0

在什麼操作系統中,您是否證明System.nanoTime()產生的輸出已被「許多微秒」關閉? – 2009-09-30 22:20:41

+0

這是在一個雙核心機器上的Linux系統,但它是一個相當老的安裝(從2007年初...)。也許這是原因。我會檢查一些更近的​​事情。另外從我記得,我有連續的電話返回相同的價值,然後跳幾個micaresconds。 – penpen 2009-09-30 22:35:16

回答

13

與獲得超精密時間測量的問題是,有些處理器不能/不會提供這種微小的增量。

據我所知,System.currentTimeMillis()System.nanoTime()是您能夠找到的最佳測量值。

注意,這兩個返回long值。

+0

現代處理器(> 1ghz)的循環速度快於1納秒,因此它們在技術上相當有能力。 – 2009-09-30 22:29:10

+2

他們可以跟蹤時間,但這並不意味着他們準確地報告時間。 – jjnguy 2009-09-30 22:30:41

+2

不要忘記,有開銷: 有一個系統調用,通常本身是微秒級(只是跳到內核和退出,但這是昂貴的時間讀取部分)。 然後,您可能會啓用預佔權加載系統,這意味着可能會安排其他某個進程。即使情況並非如此,這意味着您仍然需要跳入JVM中,即使使用JIT代碼也會產生輕微的開銷。 在原生gode中,您可以使用clock_gettime&friends API來探索高分辨率計時器的準確性。 – Vitali 2009-09-30 22:54:51

1

不幸的是,我不認爲Java RTS在這一刻已經夠成熟了。

Java的時間並儘量提供最好的價值(他們實際上委託本地代碼調用獲取籽粒時間)。但是,JVM規範使得這種粗略的時間測量免責主要針對GC活動以及底層系統的支持。

  • 即使您正在運行併發GC,某些GC活動也會阻塞所有線程。
  • 默認的linux時鐘刻度精度只有10ms。如果linux kernal不支持,Java不能讓它變得更好。

我還沒有想出如何解決#1,除非你的應用程序不需要做GC。一個體面和中等規模的應用程序可能偶爾花費幾十毫秒的GC暫停。如果您的精度要求低於10毫秒,那麼您可能運氣不好。

至於#2,您可以tune the linux kernal給予更高的精度。但是,由於現在更頻繁地切換內核上下文,因此您的盒子也越來越少。也許,我們應該從不同的角度來看待它。 OPS需要精度低於10ms的原因嗎?可以告訴Ops精確度在10ms,並且當時也查看GC日誌,所以他們知道在那段時間沒有GC活動時,精確度爲+ -10ms?

+0

」某些GC活動將阻止所有線程,即使您正在運行併發GC。「 你說得對,但另一方面,通過調整JVM參數,可以部分緩解這個問題。正如提議的那樣,是的,GC中的時間可以考慮在內,並且被刪除。 – penpen 2009-09-30 22:49:47

+0

我的觀點並不是我們無法調整它。我的觀點是,即使你調整GC,你也無法讓GC降低到你似乎喜歡的納秒級別。那是我對「體面」應用程序的定義,應該已經調整過了:) – 2009-09-30 23:27:09

5

這是Java中的一個位無意義測量時間縮短到納秒規模;偶爾的GC命中將很容易消除這種可能的準確性。在任何情況下,文檔都指出雖然它提供了納秒精度,但它與納秒精度不一樣;並且有操作系統在任何情況下都不報告納秒(這就是爲什麼您在訪問時會查找量化到1000的答案;這不是運氣,而是限制)。

不僅如此,但根據功能如何實際上是由操作系統來實現,你可能會發現通過反正(例如答案總是在最後64或128,而不是中間值)來量化結果。

這也是值得注意的是,該法的目的是爲了找到一些(附近)開始的時間,現在兩者之間的時間差;如果你把System.nanoTime()在長期運行的應用程序的啓動,然後採取System.nanoTime()很長一段時間後,它可能與實際時間很遠漂流。所以你應該只使用它少於1秒的時間;如果你需要比這更長的運行時間,毫秒應該足夠了。 (如果不是這樣,那麼補上最後幾個數字;你可能會給客戶留下深刻的印象,結果也會一樣有效。)

+0

「所以你應該只使用它少於1秒的時間」。這是一個小的重複現象。 「如果不是,那麼補上最後幾個數字」。不,他們可能想嘗試並重現此:) – penpen 2009-09-30 22:57:58

0

如果您正在尋找以納秒級別記錄某種類型的現象,你真正需要的是real-time operating system。定時器的精確度將在很大程度上取決於操作系統的實現high resolution timer和底層硬件。

但是,由於存在RTOS版本,您仍然可以使用Java。

0

JNI: 創建一個簡單函數來訪問ARM中的Intel RDTSC指令或協處理器p15的PMCCNTR寄存器。

純Java: 如果你願意延遲到時鐘滴答,你可以得到更好的值。你可以旋轉檢查System.nanoTime(),直到值改變。例如,如果您知道System.nanoTime()的值通過DELTA量每更改一次您的平臺上的10000次循環,則實際事件時間爲finalNanoTime-DELTA * ITERATIONS/10000。在進行實際測量之前,您需要「預熱」代碼。

黑客(僅適用於性能分析等): 如果垃圾收集將您拋棄,則可以始終使用在第二個jvm中運行的高優先級線程來測量時間,該線程不會創建對象。讓它在您用作時鐘的共享內存中旋轉遞增。