Pergunta

Vs. Precisão Precision

O que eu gostaria de saber é se eu deveria usar System.currentTimeMillis () ou System.nanoTime () ao atualizar posições do meu objeto no meu jogo? Sua mudança de movimento é diretamente proporcional ao tempo decorrido desde a última chamada e eu quero ser tão precisa quanto possível.

Eu li que existem alguns problemas de tempo de resolução de graves entre diferentes sistemas operacionais (ou seja, que Mac / Linux tem uma resolução de cerca de 1 ms enquanto o Windows tem uma resolução de 50ms ??). Estou primarly executar meus aplicativos em janelas e 50ms resolução parece bastante impreciso.

Existem opções melhores do que os dois que eu listados?

Todas as sugestões / comentários?

Foi útil?

Solução

Se você está olhando apenas para medições extremamente precisas de tempo decorrido , System.nanoTime() uso. System.currentTimeMillis() lhe dará o tempo decorrido possível mais preciso em milissegundos desde a época, mas System.nanoTime() lhe dá um tempo nanossegundo-preciso, em relação a algum ponto arbitrário.

A partir da documentação Java:

public static long nanoTime()

Retorna o valor atual do temporizador do sistema disponível preciso mais, em nanossegundos.

Este método só pode ser usado para medir o tempo decorrido e não é relacionada com qualquer outra noção de sistema ou tempo de relógio de parede. O valor retornado representa nanossegundos desde alguns fixo, mas o tempo arbitrária (talvez em o futuro, para que os valores podem ser negativo). Este método fornece precisão de nanossegundos, mas não necessariamente nanosegundos precisão. Não garantias são feitas sobre como freqüentemente valores mudam. diferenças em chamadas sucessivas que abrangem maiores que aproximadamente 292 anos (2 63 nanossegundos) precisamente não vai compute o tempo decorrido devido à numérica transbordamento.

Por exemplo, para medir quanto tempo algum código leva para executar:

long startTime = System.nanoTime();    
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

Veja também: Sistema JavaDoc. nanoTime () e JavaDoc System.currentTimeMillis () para mais informações.

Outras dicas

Uma vez que nenhum outro tem mencionados este ...

Não é seguro para comparar os resultados de chamadas System.nanoTime() entre diferentes threads. Mesmo se os eventos dos tópicos acontecer em uma ordem previsível, a diferença em nanossegundos pode ser positivo ou negativo.

System.currentTimeMillis() é seguro para uso entre segmentos.

Atualização por Arkadiy : Tenho observado um comportamento mais correto de System.currentTimeMillis() no Windows 7 no Oracle Java 8. O tempo foi devolvido com 1 milissegundo precisão. O código fonte no OpenJDK não mudou, então eu não sei o que faz com que o comportamento melhor.


David Holmes de Sun postou um artigo no blog um par de anos atrás, que tem um olhar muito detalhado sobre as APIs de tempo de Java (em particular System.currentTimeMillis() e System.nanoTime()), quando você iria querer usar o que, e como eles funcionam internamente.

Dentro do Hotspot VM: relógios, temporizadores e agendamento de Eventos - Parte I - Windows

Um aspecto muito interessante do temporizador usado pelo Java no Windows para APIs que têm um parâmetro cronometrado espera é que a resolução do temporizador pode mudar dependendo do que outras chamadas de API podem ter sido feitas - sistema amplo (não apenas no determinado processo). Ele mostra um exemplo onde usando Thread.sleep() fará com que esta mudança resolução.

System.nanoTime() não é suportado no JVMs mais velhos. Se isso é uma preocupação, vara com currentTimeMillis

No que diz respeito a precisão, você está quase correta. Em algumas máquinas Windows, currentTimeMillis() tem uma resolução de cerca de 10ms (não 50ms). Eu não sei por que, mas algumas máquinas Windows são tão precisos como máquinas Linux.

Eu tenho usado GAGETimer no passado com sucesso moderado.

Como já foi dito, currentTimeMillis é hora do relógio, que muda devido ao horário de verão, os usuários mudam as configurações de tempo, segundo salto, e sincronização de tempo de internet. Se seu aplicativo depende monótona crescente valores tempo decorrido, você pode preferir nanoTime vez.

Você pode pensar que os jogadores não vai ser mexer com as configurações de tempo durante o jogo, e talvez você estaria certo. Mas não subestime o rompimento devido à internet sincronização tempo, ou usuários de desktop talvez remotos. A API nanoTime é imune a este tipo de perturbação.

Se você quiser usar o tempo do relógio, mas descontinuidades Evitar devido à internet sincronismo de tempo, você pode considerar um cliente NTP como Meinberg, que "tunes" a taxa de relógio para o zero-a, em vez de apenas como acertar o relógio periodicamente.

Falo por experiência pessoal. Em um aplicativo de tempo que eu desenvolvi, eu estava ficando aleatoriamente ocorrendo picos de velocidade do vento. Demorou um tempo para eu perceber que meu timebase estava sendo perturbada pelo comportamento de tempo de relógio em um PC típico. Todos os meus problemas desapareceram quando comecei a usar nanoTime. Consistência (monotonicidade) foi mais importante para a minha aplicação de precisão cru ou precisão absoluta.

Sim, se tal precisão é exigida a utilização System.nanoTime(), mas esteja ciente de que você está, em seguida, exigindo uma Java 5+ JVM.

Em meus sistemas XP, não vejo a hora do sistema relatou a pelo menos 100 microssegundos 278 nanossegundos usando o seguinte código:

private void test() {
    System.out.println("currentTimeMillis: "+System.currentTimeMillis());
    System.out.println("nanoTime         : "+System.nanoTime());
    System.out.println();

    testNano(false);                                                            // to sync with currentTimeMillis() timer tick
    for(int xa=0; xa<10; xa++) {
        testNano(true);
        }
    }

private void testNano(boolean shw) {
    long strMS=System.currentTimeMillis();
    long strNS=System.nanoTime();
    long curMS;
    while((curMS=System.currentTimeMillis()) == strMS) {
        if(shw) { System.out.println("Nano: "+(System.nanoTime()-strNS)); }
        }
    if(shw) { System.out.println("Nano: "+(System.nanoTime()-strNS)+", Milli: "+(curMS-strMS)); }
    }

Eu tive uma boa experiência com nanoTime . Ele fornece tempo relógio de parede como dois longos (segundos desde a época e nanossegundos dentro desse segundo), usando uma biblioteca JNI. Ele está disponível com a parte JNI pré-compilados para Windows e Linux.

Por gráficos de jogos e atualizações de posição lisas, uso System.nanoTime() em vez de System.currentTimeMillis(). Troquei de currentTimeMillis () para nanoTime () em um jogo e tem uma grande melhoria visual na suavidade do movimento.

Enquanto um milésimo de segundo pode parecer como se ele já deve ser preciso, visualmente, não é. A fatores nanoTime() pode melhorar incluem:

  • posicionamento de pixels precisa abaixo resolução relógio de parede
  • capacidade de anti-pseudônimo entre pixels, se você quiser
  • Windows relógio de parede imprecisão
  • jitter relógio (inconsistência de quando a parede-relógio realmente carrapatos para a frente)

Como outras respostas sugerem, nanoTime tem um custo de desempenho se for chamado repetidamente - que seria melhor chamá-lo apenas uma vez por quadro e utilizar o mesmo valor para calcular todo o quadro

.

System.currentTimeMillis() não é seguro para o tempo decorrido porque este método é sensível às tempo real do sistema muda relógio do sistema. Você deve usar System.nanoTime. Por favor, consulte a ajuda Java System:

Sobre o método de nanoTime:

.. Este método fornece precisão de nanossegundos, mas não necessariamente nanossegundo resolução (isto é, com que frequência o valor é alterado) - não garantias são feitas, exceto que a resolução é pelo menos tão bom quanto a de currentTimeMillis () ..

Se você usar System.currentTimeMillis() o tempo decorrido pode ser negativo (Back <- para o futuro)

uma coisa aqui é a inconsistência do method.it nanoTime não dá valores muito consistentes para os mesmos input.currentTimeMillis não muito melhor em termos de desempenho e consistência, e também, embora não tão precisa quanto nanoTime, tem uma menor margem de erro, e, portanto, mais precisão em seu valor. Sugiro, portanto, que você use currentTimeMillis

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top