[英]How long it takes for one second in Java? Measure latency time in Java
我不想更改此代碼,我只對JVM,OS或內核定制/配置感興趣以獲得最佳結果!
我有一個第二個循環(1000 x 1ms)
public static void main(String[] args) throws InterruptedException {
long start = System.nanoTime();
for (int i = 0; i < 1000; i++ ) {
Thread.sleep(TimeUnit.MILLISECONDS.toMillis(1));
}
long duration = System.nanoTime() - start;
System.out.println("Loop duration " +
duration / TimeUnit.MILLISECONDS.toNanos(1) + " ms.");
}
在我的帶有內核3.12的Fedora 20上,這個循環需要1055毫秒。
這是相當不錯的結果,平均超過1100ms 。
是否可以使用自定義JVM標志或操作系統配置來加快此代碼的速度?
Loop duration 1055 ms.
調用sleep()
你基本上是告訴操作系統暫停你的線程至少X毫秒。 無法保證在此時間之后它將繼續執行,或者操作系統稍后會重新構建您的線程。 此外,最小sleep
時間及其准確性在很大程度上取決於操作系統。
編輯:另外你應該考慮到你的情況,(很可能)你的代碼正在被解釋! JAva編譯為本機代碼只有hotspots
(並且fromm這里是Hotspot JIT的名稱),它們經常被執行。 對於server
VM,這是給定代碼的10k執行。 你只有1k。
請注意,除了等待一秒鍾之外,您的代碼正在執行操作。 它正在為for循環輸入代碼,設置變量以跟蹤它並進行迭代。 但更重要的是,您必須了解您的系統還發生了什么。
您的操作系統有一個稱為調度程序的東西,它決定在任何給定時間運行的程序('進程')訪問CPU。 如果某個程序(如您的程序)進入休眠狀態(定義為“至少在x單位時間內不執行任何操作”),則調度程序通常會將其切換為另一個程序(您運行的程序很多) 。 當它重新切換回來時是非確定性的。 因此,即使您恰好在接近一秒標記(可能是)時切換回來,它也不可能完全在一秒鍾之內。 因此,“改進”這段代碼永遠無法幫助解決需要精確一秒循環的潛在問題。
另請注意,調度程序可以隨時切換程序:程序無需自願進入休眠狀態。 這是調度程序的任務; 仲裁哪些進程可以在任何特定點訪問系統資源。 因此,時間分析,特別是在這種半實現方式中,並不是特別有用。 使用IDE探查器可以獲得更好的想法,因為它們可以測量牆壁時間等內容。
也許您真正需要關注的是http://en.wikipedia.org/wiki/Real_time_Java - 如果您需要保證低延遲,您需要一個JVM 和一個經過調整的操作系統來為您提供。
據我所知,這里的一個因素是內核系統的滴答時間(我認為台式機為200 tps,服務器為100,RT系統為1000)。 這會導致小的延遲,累積達到55毫秒。 此外, sleep
調用將具有一些系統開銷,這很難自行減少。
System.currentTimeMillis
不應用作經過時間的度量。 您應該使用System.nanoTime
。 在這里尋找更多解釋。
好吧,你顯然可以分解出TimeUnit轉換並節省幾個周期。 你也可以倒數而不是倒數; 使用!= 0測試通常比與其他值比較快。
在進行任何測量之前,您還應確保代碼完全JIT(可能需要幾分鍾的運行時間)。
一般來說,微基准測試在Java中具有誤導性,並且在不知道代碼對運行時有多大貢獻的情況下進行微觀優化往往會浪費精力。 不要為這種運動而煩惱。 編寫盡可能最好的代碼,在分類實際數據上給它大量的預熱時間,然后使用分析器查看它花費時間的位置(也在實際數據上)。 這將告訴您性能調整在哪些方面實際上是高效的。 然后考慮算法改進,這往往會產生最大的好處。 再次使用新代碼進行配置,看看現在有什么熱點。 重復。
請記住,占運行時間1%的東西的無限改進需要付出無限的努力,但只能提高1%。 把你的努力放在有所作為的地方。 而且,特別是在熱點Javas中,代碼在執行期間繼續進行優化,但優化不是完全確定的,不要相信一次執行就能給出真正的性能數字。
你為什么不簡單地把它單獨睡一覺?
Thread.sleep(1000);
我真的想做1000個睡眠命令我推薦這個:
public static void main(String[] args) throws InterruptedException {
// This line is for timing reasons only!
long start = System.currentTimeMillis();
final long startTime = System.currentTimeMillis();
long waitTime;
for (int i = 0; i < 1000; i++ ) {
// Get the time you want to end with. Then substact your current system time!
waitTime = (startTime + i + 1)- System.currentTimeMillis();
// Only wait if it would wait (If waitTime is greater than 0.
// Everything below 0 will also throw a execption!
if(waitTime > 0)
Thread.sleep(waitTime);
}
// Same for those...
long duration = System.currentTimeMillis() - start;
System.out.println("Loop duration " + duration + " ms.");
}
這將確保您只等到目前有意義!
不幸的是,我的問題被誤解了。
實時java被廢棄,因此使用Realtime java的建議無效。
經過一些研究,這個測試在一些Windows機器上有最好的結果。
在測試的Windows 8.1上,此測試打印正好1000毫秒。
其他結果:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.