A precisão de System.nanoTime () para medir o tempo decorrido diminui após uma chamada para Thread.sleep ()

Estou encontrando um problema realmente incomum aqui. Parece que a chamada de Thread.sleep (n), em que n> 0, faria com que as seguintes chamadas System.nanoTime () fossem menos previsíveis.

O código abaixo demonstra o problema.

A execução no meu computador (rMBP 15 "2015, OS X 10.11, jre 1.8.0_40-b26) gera o seguinte resultado:

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

Em uma máquina virtual executando o Windows 8 (VMware Horizon, Windows 8.1, são 1.8.0_60-b27):

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

No entanto, executando-o em um servidor corporativo (VMware, RHEL 6.7, jre 1.6.0_45-b06):

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

O que é surpreendentemente o resultado que eu espero.

Claramente, o Thread.sleep (1) afeta o cálculo do código abaixo. Eu não tenho idéia do por que isso acontece. Alguém tem uma pista?

Obrigado!

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

Basicamente, estou executando uma pesquisa em um loop while que interrompe cada iteração chamando Thread.sleep (). Quero excluir o tempo de suspensão do tempo total gasto para executar a pesquisa, por isso estou usando System.nanoTime () para registrar os horários de início e término. No entanto, como você notou acima, isso não funciona bem.

Existe uma maneira de remediar isso?

Obrigado por qualquer contribuição!

questionAnswers(3)

yourAnswerToTheQuestion