gpt4 book ai didi

java - 在调用 Thread.sleep() 后,System.nanoTime() 测量耗时的准确性降低

转载 作者:行者123 更新时间:2023-11-30 06:11:45 28 4
gpt4 key购买 nike

我在这里遇到了一个非常不寻常的问题。似乎调用 Thread.sleep(n),其中 n > 0 会导致以下 System.nanoTime() 调用难以预测。

下面的代码演示了这个问题。

在我的电脑(rMBP 15"2015,OS X 10.11,jre 1.8.0_40-b26)上运行它输出以下结果:

Control: 48497
Random: 36719
Thread.sleep(0): 48044
Thread.sleep(1): 832271

在运行 Windows 8 的虚拟机上(VMware Horizo​​n、Windows 8.1 均为 1.8.0_60-b27):

Control: 98974
Random: 61019
Thread.sleep(0): 115623
Thread.sleep(1): 282451

但是,在企业服务器(VMware、RHEL 6.7、jre 1.6.0_45-b06)上运行它:

Control: 1385670
Random: 1202695
Thread.sleep(0): 1393994
Thread.sleep(1): 1413220

这出乎我的意料。

很明显 Thread.sleep(1) 会影响下面代码的计算。我不知道为什么会这样。有人知道吗?

谢谢!

public class Main {
public static void main(String[] args) {
int N = 1000;
long timeElapsed = 0;
long startTime, endTime = 0;

for (int i = 0; i < N; i++) {
startTime = System.nanoTime();
//search runs here
endTime = System.nanoTime();

timeElapsed += endTime - startTime;
}

System.out.println("Control: " + timeElapsed);

timeElapsed = 0;

for (int i = 0; i < N; i++) {
startTime = System.nanoTime();
//search runs here
endTime = System.nanoTime();

timeElapsed += endTime - startTime;

for (int j = 0; j < N; j++) {
int k = (int) Math.pow(i, j);
}
}

System.out.println("Random: " + timeElapsed);

timeElapsed = 0;

for (int i = 0; i < N; i++) {
startTime = System.nanoTime();
//search runs here
endTime = System.nanoTime();

timeElapsed += endTime - startTime;

try {
Thread.sleep(0);
} catch (InterruptedException e) {
break;
}
}

System.out.println("Thread.sleep(0): " + timeElapsed);

timeElapsed = 0;

for (int i = 0; i < N; i++) {
startTime = System.nanoTime();
//search runs here
endTime = System.nanoTime();

timeElapsed += endTime - startTime;

try {
Thread.sleep(2);
} catch (InterruptedException e) {
break;
}
}

System.out.println("Thread.sleep(1): " + timeElapsed);
}
}

基本上,我在 while 循环中运行搜索,它通过调用 Thread.sleep() 在每次迭代中暂停。我想从运行搜索的总时间中排除 sleep 时间,因此我使用 System.nanoTime() 来记录开始和结束时间。但是,正如您在上面注意到的那样,这效果不佳。

有办法解决这个问题吗?

感谢任何输入!

最佳答案

这是一个复杂的主题,因为 JVM 使用的计时器高度依赖于 CPU 和操作系统,并且还会随着 JVM 版本的变化而变化(例如,通过使用更新的操作系统 API)。虚拟机也可能会限制它们传递给 guest 的 CPU 功能,与裸机设置相比,这可能会改变选择。

在 x86 上,RDTSC 指令提供所有时钟中最低的延迟和最好的粒度,但在某些配置下,它作为时间源不可用或不够可靠。

在 Linux 上,您应该检查内核启动消息 (dmesg)、tsc 相关的 /proc/cpuinfo 标志和选定的 /sys/devices/system/时钟源/*/current_clocksource。默认情况下,内核将尝试使用 TSC,如果不这样做,可能是有原因的。

对于一些历史,您可能想阅读以下内容,但请注意其中一些文章可能有点过时,这些年来 TSC 的可靠性已经提高了很多:

关于java - 在调用 Thread.sleep() 后,System.nanoTime() 测量耗时的准确性降低,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33716359/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com