Système.currentTimeMillis vs système.nanoTime

L'Exactitude De La Vs. Précision

Ce que je voudrais savoir c'est si je dois utiliser Système.currentTimeMillis() ou Système.nanoTime () lors de la mise à jour des positions de mon objet dans mon jeu? Leur changement de mouvement est directement proportionnel au temps écoulé depuis le dernier appel et je veux être aussi précis que possible.

J'ai lu qu'il y a de sérieux problèmes de résolution de temps entre différents systèmes d'exploitation (à savoir que Mac / Linux ont un Résolution de 1 ms alors que Windows a une résolution de 50 ms??). Je cours principalement mes applications sur windows et la résolution 50ms semble assez inexacte.

Y a-t-il de meilleures options que les deux que j'ai énumérées?

Des suggestions / commentaires?

320
demandé sur mmcdole 2008-12-09 04:58:47

10 réponses

Si vous cherchez simplement des mesures extrêmement précises de Temps écoulé , Utilisez System.nanoTime(). {[3] } vous donnera le temps écoulé le plus précis possible en millisecondes depuis l'époque, mais System.nanoTime() vous donnera un temps précis en nanosecondes, par rapport à un point arbitraire.

À partir de la Documentation Java:

public static long nanoTime()

Renvoie la valeur actuelle de la minuterie système la plus précise disponible, en nanosecondes.

Cette méthode ne peut être utilisée pour mesurer le temps et n'est pas liés à toute autre notion de système ou l'horloge murale. La valeur retournée représente des nanosecondes depuis temps fixe mais arbitraire (peut-être dans l'avenir, de sorte que les valeurs peuvent être négatif). Cette méthode permet d' précision nanoseconde, mais pas nécessairement précision nanoseconde. Aucun des garanties sont faites sur la façon dont les valeurs changent fréquemment. Différence dans les appels successifs qui couvrent plus moins d'environ 292 ans (263 nanosecondes) ne sera pas précisément calculer le temps écoulé En raison de débordement.

Par exemple, pour mesurer le temps d'exécution d'un code:

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

Voir Aussi: système JavaDoc.nanoTime () et Système JavaDoc.currentTimeMillis () pour plus d'informations.

286
répondu dancavallaro 2018-01-11 06:56:30

Fil-Sécurité

Car personne d'autre ne l'a mentionné...

Pas Sûr

Il est pas sûr de comparer les résultats des appels System.nanoTime() entre différents threads. Même si les événements des threads se produisent dans un ordre prévisible, la différence en nanosecondes peut être positive ou négative.

Coffre-fort

System.currentTimeMillis() est sûr pour une utilisation entre les threads.

83
répondu gubby 2018-02-20 07:04:16

Mise à jour par Arkadiy: j'ai observé un comportement plus correct de System.currentTimeMillis() sur Windows 7 dans Oracle Java 8. Le temps a été retourné avec une précision de 1 milliseconde. Le code source dans OpenJDK n'a pas changé, donc je ne sais pas ce qui cause le meilleur comportement.


David Holmes de Sun a posté un article de blog il y a quelques années qui a un regard très détaillé sur les API de synchronisation Java (en particulier System.currentTimeMillis() et System.nanoTime()), quand vous voulez utiliser lequel, et comment ils fonctionnent interne.

À l'intérieur de la machine virtuelle Hotspot: Horloges, minuteries et événements de planification-Partie I-Windows

Un aspect très intéressant de la minuterie utilisée par Java sur Windows pour les API qui ont un paramètre d'attente temporisée est que la résolution de la minuterie peut changer en fonction de ce que d'autres appels D'API peuvent avoir été effectués-à l'échelle du système (pas seulement dans le processus particulier). Il montre un exemple où l'utilisation de Thread.sleep() provoquera ce changement de résolution.

56
répondu Michael Burr 2017-05-23 12:26:27

System.nanoTime() n'est pas pris en charge dans les anciennes JVM. Si c'est une préoccupation, s'en tenir à currentTimeMillis

En ce qui concerne la précision, vous avez presque raison. Sur certaines machines Windows, currentTimeMillis() a une résolution d'environ 10 ms (pas 50 ms). Je ne sais pas pourquoi, mais certaines machines Windows sont tout aussi précises que les machines Linux.

J'ai utilisé GAGETimer, dans le passé, avec un succès modéré.

9
répondu Paul Morel 2014-10-26 07:38:48

Comme d'autres l'ont dit, currentTimeMillis est l'Heure de l'horloge, qui change en raison de l'heure d'été, des utilisateurs qui changent les paramètres de l'heure, des secondes intercalaires et de la synchronisation de l'heure internet. Si votre application dépend de l'augmentation monotone des valeurs de temps écoulé, vous pouvez préférer nanoTime à la place.

Vous pourriez penser que les joueurs ne seront pas jouer avec les paramètres de temps pendant le jeu, et peut-être que vous auriez raison. Mais ne sous-estimez pas la perturbation due à la synchronisation de l'heure internet, ou peut-être à distance utilisateurs de pc de bureau. L'API nanoTime est à l'abri de ce genre de perturbation.

Si vous voulez utiliser l'heure d'horloge, mais éviter les discontinuités dues à la synchronisation de l'heure internet, vous pouvez envisager un client NTP tel que Meinberg, qui "règle" la fréquence d'horloge à zéro, au lieu de simplement réinitialiser l'horloge périodiquement.

Je parle par expérience personnelle. Dans une application météorologique que j'ai développée, j'obtenais des pics de vitesse du vent qui se produisaient aléatoirement. Il a fallu un certain temps pour moi de réaliser que mon la base de temps était perturbée par le comportement de l'heure d'horloge sur un PC typique. Tous mes problèmes ont disparu quand j'ai commencé à utiliser nanoTime. La cohérence (monotonie) était plus importante pour mon application que la précision brute ou la précision absolue.

7
répondu KarlU 2013-09-25 00:28:56

Oui, si une telle précision est requise, utilisez System.nanoTime(), mais sachez que vous avez alors besoin d'une jvm Java 5+.

Sur mes systèmes XP, je vois le temps système rapporté à au moins 100 microsecondes 278 nanosecondes en utilisant le code suivant:

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)); }
    }
4
répondu Lawrence Dol 2014-10-27 15:12:04

J'ai eu une bonne expérience avec nanotime . Il fournit le temps d'horloge murale en deux longues (secondes depuis l'époque et nanosecondes dans cette seconde), en utilisant une bibliothèque JNI. Il est disponible avec la partie JNI précompilée Pour Windows et Linux.

2
répondu Jon Bright 2011-04-21 11:01:25

Pour les graphiques de jeu et les mises à jour de position fluides, utilisez System.nanoTime() plutôt que System.currentTimeMillis(). Je suis passé de currentTimeMillis () à nanoTime () dans un jeu et j'ai obtenu une amélioration visuelle majeure de la douceur du mouvement.

Alors qu'une milliseconde peut sembler comme si elle devrait déjà être précise, visuellement ce n'est pas le cas. Les facteurs nanoTime() peuvent améliorer:

  • positionnement précis des pixels sous la résolution de l'horloge murale
  • capacité d'anti-alias entre les pixels, si vous voulez
  • Fenêtres horloge murale imprécision
  • gigue de l'horloge (incohérence du moment où l'horloge murale avance)

Comme le suggèrent d'autres réponses, nanoTime a un coût de performance s'il est appelé à plusieurs reprises-il serait préférable de l'appeler une seule fois par image, et d'utiliser la même valeur pour calculer la trame entière.

1
répondu Thomas W 2017-08-17 02:29:35

System.currentTimeMillis() n'est pas sûr pour le temps écoulé car cette méthode est sensible aux changements d'horloge en temps réel du système. Vous devriez utiliser System.nanoTime. Veuillez vous référer à L'aide du système Java:

Sur nanoTime méthode:

.. Cette méthode fournit une précision nanoseconde, mais pas nécessairement résolution nanoseconde (c'est - à-dire à quelle fréquence la valeur change) - Non les garanties sont faites sauf que la résolution est au moins aussi bonne que que de currentTimeMillis ()..

Si vous utilisez System.currentTimeMillis() votre temps écoulé peut être négatif (Retour

0
répondu Ricardo Gasca 2017-11-28 15:48:15

Une chose ici est l'incohérence du nanoTime method.it ne donne pas de valeurs très cohérentes pour la même entrée.currentTimeMillis fait beaucoup mieux en termes de performance et de cohérence,et aussi ,bien que pas aussi précis que nanoTime,a une marge d'erreur plus faible,et donc plus de précision dans sa valeur. je suggère donc que vous utilisiez currentTimeMillis

-4
répondu sarvesh 2012-04-24 04:52:10