System.currentTimeMillis vs System.nanoTime

JavaTimerTime Precision

Java Problem Overview


Accuracy Vs. Precision

What I would like to know is whether I should use System.currentTimeMillis() or System.nanoTime() when updating my object's positions in my game? Their change in movement is directly proportional to the elapsed time since the last call and I want to be as precise as possible.

I've read that there are some serious time-resolution issues between different operating systems (namely that Mac / Linux have an almost 1 ms resolution while Windows has a 50ms resolution??). I'm primarly running my apps on windows and 50ms resolution seems pretty inaccurate.

Are there better options than the two I listed?

Any suggestions / comments?

Java Solutions


Solution 1 - Java

If you're just looking for extremely precise measurements of elapsed time, use System.nanoTime(). System.currentTimeMillis() will give you the most accurate possible elapsed time in milliseconds since the epoch, but System.nanoTime() gives you a nanosecond-precise time, relative to some arbitrary point.

From the Java Documentation: > public static long nanoTime() > >Returns the current value of the most precise available system timer, in nanoseconds. > > This method can only be used to > measure elapsed time and is not > related to any other notion of system > or wall-clock time. The value returned > represents nanoseconds since some > fixed but arbitrary origin time (perhaps in > the future, so values may be > negative). This method provides > nanosecond precision, but not > necessarily nanosecond accuracy. No > guarantees are made about how > frequently values change. Differences > in successive calls that span greater > than approximately 292 years (263 > nanoseconds) will not accurately > compute elapsed time due to numerical > overflow.

For example, to measure how long some code takes to execute:

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

See also: JavaDoc System.nanoTime() and JavaDoc System.currentTimeMillis() for more info.

Solution 2 - Java

Since no one else has mentioned this…

It is not safe to compare the results of System.nanoTime() calls between different JVMs, each JVM may have an independent 'origin' time.

System.currentTimeMillis() will return the (approximate) same value between JVMs, because it is tied to the system wall clock time.

If you want to compute the amount of time that has elapsed between two events, like a stopwatch, use nanoTime(); changes in the system wall-clock make currentTimeMillis() incorrect for this use case.

Solution 3 - Java

Update by Arkadiy: I've observed more correct behavior of System.currentTimeMillis() on Windows 7 in Oracle Java 8. The time was returned with 1 millisecond precision. The source code in OpenJDK has not changed, so I do not know what causes the better behavior.


David Holmes of Sun posted a blog article a couple years ago that has a very detailed look at the Java timing APIs (in particular System.currentTimeMillis() and System.nanoTime()), when you would want to use which, and how they work internally.

Inside the Hotspot VM: Clocks, Timers and Scheduling Events - Part I - Windows

One very interesting aspect of the timer used by Java on Windows for APIs that have a timed wait parameter is that the resolution of the timer can change depending on what other API calls may have been made - system wide (not just in the particular process). He shows an example where using Thread.sleep() will cause this resolution change.

Solution 4 - Java

As others have said, currentTimeMillis is clock time, which changes due to daylight saving time (not: daylight saving & time zone are unrelated to currentTimeMillis, the rest is true), users changing the time settings, leap seconds, and internet time sync. If your app depends on monotonically increasing elapsed time values, you might prefer nanoTime instead.

You might think that the players won't be fiddling with the time settings during game play, and maybe you'd be right. But don't underestimate the disruption due to internet time sync, or perhaps remote desktop users. The nanoTime API is immune to this kind of disruption.

If you want to use clock time, but avoid discontinuities due to internet time sync, you might consider an NTP client such as Meinberg, which "tunes" the clock rate to zero it in, instead of just resetting the clock periodically.

I speak from personal experience. In a weather application that I developed, I was getting randomly occurring wind speed spikes. It took a while for me to realize that my timebase was being disrupted by the behavior of clock time on a typical PC. All my problems disappeared when I started using nanoTime. Consistency (monotonicity) was more important to my application than raw precision or absolute accuracy.

Solution 5 - Java

System.nanoTime() isn't supported in older JVMs. If that is a concern, stick with currentTimeMillis

Regarding accuracy, you are almost correct. On SOME Windows machines, currentTimeMillis() has a resolution of about 10ms (not 50ms). I'm not sure why, but some Windows machines are just as accurate as Linux machines.

I have used GAGETimer in the past with moderate success.

Solution 6 - Java

Yes, if such precision is required use System.nanoTime(), but be aware that you are then requiring a Java 5+ JVM.

On my XP systems, I see system time reported to at least 100 microseconds 278 nanoseconds using the following code:

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

Solution 7 - Java

For game graphics & smooth position updates, use System.nanoTime() rather than System.currentTimeMillis(). I switched from currentTimeMillis() to nanoTime() in a game and got a major visual improvement in smoothness of motion.

While one millisecond may seem as though it should already be precise, visually it is not. The factors nanoTime() can improve include:

  • accurate pixel positioning below wall-clock resolution
  • ability to anti-alias between pixels, if you want
  • Windows wall-clock inaccuracy
  • clock jitter (inconsistency of when wall-clock actually ticks forward)

As other answers suggest, nanoTime does have a performance cost if called repeatedly -- it would be best to call it just once per frame, and use the same value to calculate the entire frame.

Solution 8 - Java

System.currentTimeMillis() is not safe for elapsed time because this method is sensitive to the system realtime clock changes of the system. You should use System.nanoTime. Please refer to Java System help:

About nanoTime method:

> .. This method provides nanosecond precision, but not necessarily > nanosecond resolution (that is, how frequently the value changes) - no > guarantees are made except that the resolution is at least as good as > that of currentTimeMillis()..

If you use System.currentTimeMillis() your elapsed time can be negative (Back <-- to the future)

Solution 9 - Java

I've had good experience with nanotime. It provides wall-clock time as two longs (seconds since the epoch and nanoseconds within that second), using a JNI library. It's available with the JNI part precompiled for both Windows and Linux.

Solution 10 - Java

one thing here is the inconsistency of the nanoTime method.it does not give very consistent values for the same input.currentTimeMillis does much better in terms of performance and consistency,and also ,though not as precise as nanoTime,has a lower margin of error,and therefore more accuracy in its value. i would therefore suggest that you use currentTimeMillis

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmmcdoleView Question on Stackoverflow
Solution 1 - JavadancavallaroView Answer on Stackoverflow
Solution 2 - JavagubView Answer on Stackoverflow
Solution 3 - JavaMichael BurrView Answer on Stackoverflow
Solution 4 - JavaKarlUView Answer on Stackoverflow
Solution 5 - JavaPaul MorelView Answer on Stackoverflow
Solution 6 - JavaLawrence DolView Answer on Stackoverflow
Solution 7 - JavaThomas WView Answer on Stackoverflow
Solution 8 - JavaRicardo GascaView Answer on Stackoverflow
Solution 9 - JavaJon BrightView Answer on Stackoverflow
Solution 10 - JavasarveshView Answer on Stackoverflow