Question

Précision contre.Précision

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

J'ai lu qu'il existe de sérieux problèmes de résolution temporelle entre les différents systèmes d'exploitation (à savoir que Mac/Linux ont une résolution de près de 1 ms alors que Windows a une résolution de 50 ms ??).J'exécute principalement mes applications sous Windows et une résolution de 50 ms semble assez inexacte.

Existe-t-il de meilleures options que les deux que j’ai énumérées ?

Des suggestions/commentaires ?

Était-ce utile?

La solution

Si vous recherchez uniquement des mesures extrêmement précises du temps écoulé , utilisez System.nanoTime(). System.currentTimeMillis() vous donnera le temps écoulé le plus précis possible en millisecondes depuis l'époque, mais <=> vous donnera un temps précis en nanosecondes, par rapport à un point quelconque.

À partir de la documentation Java:

public static long nanoTime()
     

Renvoie la valeur actuelle du temporisateur système le plus précis disponible, en nanosecondes.

     

Cette méthode ne peut être utilisée que pour   mesurer le temps écoulé et n'est pas   liée à toute autre notion de système   ou l'heure murale. La valeur retournée   représente des nanosecondes puisque certains   temps fixe mais arbitraire (peut-être en   l'avenir, alors les valeurs peuvent être   négatif). Cette méthode fournit   Précision nanoseconde, mais pas   nécessairement une précision nanoseconde. Non   des garanties sont données sur la manière dont   les valeurs changent fréquemment. Différences   dans les appels successifs qui couvrent plus   qu’environ 292 ans (2 63   nanosecondes) ne sera pas exactement   calculer le temps écoulé en raison de numérique   débordement.

Par exemple, pour mesurer le temps nécessaire à l'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 JavaDoc System.currentTimeMillis () pour plus d'informations.

Autres conseils

Étant donné que personne d'autre n'a mentionné cela & # 8230;

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

System.currentTimeMillis() est sans danger pour les échanges entre les threads.

Mise à jour par Arkadiy : j'ai observé un comportement plus correct de System.currentTimeMillis() sous Windows 7 dans Oracle Java 8. Le temps a été renvoyé 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 publié il y a quelques années un article sur son blog qui présente de manière très détaillée les API de synchronisation Java (en particulier System.nanoTime() et Thread.sleep()), quand vous voulez utiliser lesquelles et leur mode de fonctionnement. en interne.

À l'intérieur du serveur virtuel VM: Horloges, minuteries et événements de planification - Partie I - Windows

Un aspect très intéressant du minuteur utilisé par Java sous Windows pour les API qui ont un paramètre d'attente minuté est que la résolution du minuteur peut changer en fonction des appels passés par d'autres API, à l'échelle du système (et pas seulement processus particulier). Il montre un exemple où utiliser <=> entraînera ce changement de résolution.

System.nanoTime() n'est pas pris en charge par les anciennes JVM. Si cela vous préoccupe, restez avec currentTimeMillis

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

J'ai utilisé GAGETimer avec un succès modéré.

Comme d'autres l'ont déjà dit, currentTimeMillis correspond à l'heure de l'horloge, qui change en raison de l'heure d'été, des utilisateurs qui modifient 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 préférerez peut-être nanoTime.

Vous pensez peut-être que les joueurs ne joueront pas avec les réglages de l'heure pendant le jeu, et vous auriez peut-être raison. Mais ne sous-estimez pas les perturbations dues à la synchronisation de l'heure sur Internet, ou peut-être aux utilisateurs de bureau distants. L'API nanoTime est à l'abri de ce type de perturbation.

Si vous souhaitez utiliser l'heure d'horloge tout en évitant les discontinuités dues à la synchronisation de l'heure sur Internet, vous pouvez envisager un client NTP tel que Meinberg, qui & "Syntonise &"; le taux d'horloge pour le mettre à zéro, au lieu de simplement réinitialiser l'horloge périodiquement.

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

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

Sur mes systèmes XP, l'heure du système est signalée à au moins 100 microsecondes 278 nanosecondes à l'aide du 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)); }
    }

J'ai eu une bonne expérience avec nanotime.Il fournit une heure d'horloge murale en deux longueurs (secondes depuis l'époque et nanosecondes au sein de cette seconde), à ​​l'aide d'une bibliothèque JNI.Il est disponible avec la partie JNI précompilée pour Windows et Linux.

Pour les graphiques de jeu & amp; mises à jour de position en douceur, 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 fluidité du mouvement.

Même si une milliseconde peut sembler devoir déjà être précise, ce n’est pas le cas visuellement. Les facteurs nanoTime() pouvant être améliorés incluent:

  • positionnement précis des pixels en dessous de la résolution de l'horloge murale
  • possibilité d'anti-alias entre pixels, si vous le souhaitez
  • imprécision de l'horloge murale Windows
  • instabilité de l'horloge (incohérence quant au moment où l'horloge murale avance en avant)

Comme d'autres réponses le suggèrent, si vous appelez plusieurs fois nanoTime, il est préférable de l'appeler une fois par image et d'utiliser la même valeur pour calculer l'intégralité de l'image.

System.currentTimeMillis() n'est pas sans danger 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 reporter à l'aide de Java System:

À propos de la méthode nanoTime:

  

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

Si vous utilisez <=> votre temps écoulé peut être négatif (Retour < - vers le futur)

Une chose est l’incohérence de la méthode nanoTime. Elle ne donne pas des valeurs très cohérentes pour le même input.currentTimeMillis fait beaucoup mieux en termes de performances et de cohérence, et aussi, même si elle n’est pas aussi précise que nanoTime, marge d'erreur, et donc plus de précision dans sa valeur. Je vous suggère donc d'utiliser currentTimeMillis

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top