调用Thread.sleep()后,System.nanoTime()测量经过的时间的准确度会降低 [英] Accuracy of System.nanoTime() to measure time elapsed decreases after a call to Thread.sleep()

查看:153
本文介绍了调用Thread.sleep()后,System.nanoTime()测量经过的时间的准确度会降低的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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

 控制:48497 
随机:36719
Thread.sleep(0):48044
Thread.sleep( 1):832271

在运行Windows 8的虚拟机上(VMware Horizo​​n,Windows 8.1,为1.8。 0_60-b27):

 控制:98974 
随机:61019
Thread.sleep(0): 115623
Thread.sleep(1):282451

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

 控制:1385670 
随机:1202695
Thread.sleep(0):1393994
Thread.sleep(1):1413220

令人惊讶的是我期望的结果。



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



谢谢!

 公共类主要{
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();
//搜索在这里运行
endTime = System.nanoTime();

timeElapsed + = endTime - startTime;
}

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

timeElapsed = 0;

for(int i = 0; i< N; i ++){
startTime = System.nanoTime();
//搜索在这里运行
endTime = System.nanoTime();

timeElapsed + = endTime - startTime;

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

System.out.println(随机:+ timeElapsed);

timeElapsed = 0;

for(int i = 0; i< N; i ++){
startTime = System.nanoTime();
//搜索在这里运行
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();
//搜索在这里运行
endTime = System.nanoTime();

timeElapsed + = endTime - startTime;

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

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

我基本上会在一段时间内进行搜索 - 循环,通过调用Thread.sleep()在每次迭代中休息。我想从运行搜索所花费的总时间中排除休眠时间,因此我使用System.nanoTime()来记录开始和结束时间。但是,正如您在上面提到的那样,这种方法效果不佳。



有没有办法解决这个问题?



<感谢任何输入!

解决方案

这是一个复杂的主题,因为JVM使用的定时器是高度CPU和操作系统 - 依赖,也随Java运行时版本而变化。虚拟机还可能限制它们传递给访客的CPU功能,这可能会改变相对于裸机设置的选择。



您可能需要阅读以下内容,但请注意其中一些文章可能有点陈旧,多年来TSC的可靠性有了很大提高:





在linux上你应该检查tsc相关 / proc / cpuinfo 标志和选定的 / sys / devices / system / clocksource / * / current_clocksource


I'm encountering a really unusual issue here. It seems that the calling of Thread.sleep(n), where n > 0 would cause the following System.nanoTime() calls to be less predictable.

The code below demonstrates the issue.

Running it on my computer (rMBP 15" 2015, OS X 10.11, jre 1.8.0_40-b26) outputs the following result:

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

On a Virtual Machine running Windows 8 (VMware Horizon, Windows 8.1, are 1.8.0_60-b27):

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

However, running it on an enterprise server (VMware, RHEL 6.7, jre 1.6.0_45-b06):

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

Which is surprisingly the result I expect.

Clearly the Thread.sleep(1) affects the computation of the below code. I have no idea why this happens. Does anyone have a clue?

Thanks!

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);
    }
}

Basically I'm running a search within a while-loop which takes a break every iteration by calling Thread.sleep(). I want to exclude the sleep time from the overall time taken to run the search, so I'm using System.nanoTime() to record the start and finishing times. However, as you notice above, this doesn't work well.

Is there a way to remedy this?

Thanks for any input!

解决方案

This is a complex topic because the timers used by the JVM are highly CPU- and OS-dependent and also change with Java runtime versions. VMs may also limit the CPU capabilities they pass through to guests, which may alter the choices relative to a bare metal setup.

You may want to read the following, but note that some of those articles may be a bit dated, TSC reliability has improved a lot over the years:

On linux you should check the tsc-related /proc/cpuinfo flags and the selected /sys/devices/system/clocksource/*/current_clocksource

这篇关于调用Thread.sleep()后,System.nanoTime()测量经过的时间的准确度会降低的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆