System.Currenttimemillis VS System.Nanotime

System.currentTimeMillis vs System.nanoTime

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.

Is System.nanoTime(); or System.currentTimeMillis(); better for a game

You should be using whichever is appropriate to your needs.

The two examples you gave are fundamentally different:

  • For animations, you simply need to meet the demands of the screen refresh rate which will be less that 100 times per second. For that a millisecond clock is fine. (Beyond 50 or so refreshes a second, a typical human can't tell the difference.)

  • For game loops, you could make an argument that "fairness" means you should make the clocks as accurate as possible. (And I'm sure some game players would make that argument.) If you accept that argument, then nanosecond clocks are more appropriate.

Nobody is likely to actually1 tell the difference between using millisecond or nanosecond clocks in games and other applications where the primary goal is smooth human-computer interaction.

In short: there is no "right" way.


1 - They may think that they can tell, but it wouldn't stand up to rigorous scientific testing.

Java System.nanoTime() vs System.currentTimeMillis(). Why do they have different outputs?

Read the method's javadoc

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). The same
origin is used by all invocations of this method in an instance of a
Java virtual machine; other virtual machine instances are likely to
use a different origin.

nanoTime() is not showing you the time.

Why is System.nanoTime() way slower (in performance) than System.currentTimeMillis()?

From this Oracle blog:

System.currentTimeMillis() is implemented using the
GetSystemTimeAsFileTime method, which essentially just reads the low
resolution time-of-day value that Windows maintains. Reading this
global variable is naturally very quick - around 6 cycles according to
reported information.

System.nanoTime() is implemented using the
QueryPerformanceCounter/ QueryPerformanceFrequency API (if available,
else it returns currentTimeMillis*10^6).
QueryPerformanceCounter(QPC) is implemented in different ways
depending on the hardware it's running on. Typically it will use
either the programmable-interval-timer (PIT), or the ACPI power
management timer (PMT), or the CPU-level timestamp-counter (TSC).
Accessing the PIT/PMT requires execution of slow I/O port instructions
and as a result the execution time for QPC is in the order of
microseconds. In contrast reading the TSC is on the order of 100 clock
cycles (to read the TSC from the chip and convert it to a time value
based on the operating frequency).

Perhaps this answer the question. The two methods use different number of clock cycles, thus resulting in slow speed of the later one.

Further in that blog in the conclusion section:

If you are interested in measuring/calculating elapsed time, then always use System.nanoTime(). On most systems it will give a resolution on the order of microseconds. Be aware though, this call can also take microseconds to execute on some platforms.

System.nanoTime vs System.currentTimeMillis

As has been mentioned, computing a new origin each time means you are subject to error.

//                               ______ delay _______
// v v
long origin = (long)(System.currentTimeMillis() - System.nanoTime() / 1e6);
// ^
// truncation

If you modify your program so you also compute the origin difference, you'll find out it's very small. About 200ns average I measured which is about right for the time delay.

Using multiplication instead of division (which should be OK without overflow for another couple hundred years) you'll also find that the number of origins computed that fail the equality check is much larger, about 99%. If the reason for error is because of the time delay, they would only pass when the delay happens to be identical to the last one.

A much simpler test is to accumulate elapsed time over some number of subsequent calls to nanoTime and see if it checks out with the first and last calls:

public class SimpleTimeCoherencyTest {
public static void main(String[] args) {
final long anchorNanos = System.nanoTime();

long lastNanoTime = System.nanoTime();
long accumulatedNanos = lastNanoTime - anchorNanos;

long numCallsSinceAnchor = 1L;

for(int i = 0; i < 100; i++) {
TestRun testRun = new TestRun(accumulatedNanos, lastNanoTime);

Thread t = new Thread(testRun);
t.start();

try {
t.join();
} catch(InterruptedException ie) {}

lastNanoTime = testRun.lastNanoTime;
accumulatedNanos = testRun.accumulatedNanos;
numCallsSinceAnchor += testRun.numCallsToNanoTime;
}

System.out.println(numCallsSinceAnchor);
System.out.println(accumulatedNanos);
System.out.println(lastNanoTime - anchorNanos);
}

static class TestRun
implements Runnable {
volatile long accumulatedNanos;
volatile long lastNanoTime;
volatile long numCallsToNanoTime;

TestRun(long acc, long last) {
accumulatedNanos = acc;
lastNanoTime = last;
}

@Override
public void run() {
long lastNanos = lastNanoTime;
long currentNanos;

do {
currentNanos = System.nanoTime();
accumulatedNanos += currentNanos - lastNanos;
lastNanos = currentNanos;
numCallsToNanoTime++;
} while(currentNanos - lastNanoTime <= 100000000L);

lastNanoTime = lastNanos;
}
}
}

That test does indicate the origin is the same (or at least the error is zero-mean).

System.nanoTime and System.currentTimeMillis()

From the Java System documentation:

[System.nanoTime] Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds.

This means System.nanoTime() returns the elapsed running time of the JVM in nanos, whereas System.currentTimeMillis() returns the time in milliseconds since midnight, January 1, 1970 UTC.

This results in a non-consistent nanoTime over each run.

Why do System.nanoTime() and System.currentTimeMillis() drift apart so rapidly?

You might find this Sun/Oracle blog post about JVM timers to be of interest.

Here are a couple of the paragraphs from that article about JVM timers under Windows:

System.currentTimeMillis() is implemented using the GetSystemTimeAsFileTime method, which essentially just reads the low resolution time-of-day value that Windows maintains. Reading this global variable is naturally very quick - around 6 cycles according to reported information. This time-of-day value is updated at a constant rate regardless of how the timer interrupt has been programmed - depending on the platform this will either be 10ms or 15ms (this value seems tied to the default interrupt period).

System.nanoTime() is implemented using the QueryPerformanceCounter / QueryPerformanceFrequency API (if available, else it returns currentTimeMillis*10^6). QueryPerformanceCounter(QPC) is implemented in different ways depending on the hardware it's running on. Typically it will use either the programmable-interval-timer (PIT), or the ACPI power management timer (PMT), or the CPU-level timestamp-counter (TSC). Accessing the PIT/PMT requires execution of slow I/O port instructions and as a result the execution time for QPC is in the order of microseconds. In contrast reading the TSC is on the order of 100 clock cycles (to read the TSC from the chip and convert it to a time value based on the operating frequency). You can tell if your system uses the ACPI PMT by checking if QueryPerformanceFrequency returns the signature value of 3,579,545 (ie 3.57MHz). If you see a value around 1.19Mhz then your system is using the old 8245 PIT chip. Otherwise you should see a value approximately that of your CPU frequency (modulo any speed throttling or power-management that might be in effect.)

System.currenTimeInMillis() vs System.nanoTime()

In this case I've found following blog post excerpt useful:

If you are interested in measuring absolute time then always use
System.currentTimeMillis(). Be aware that its resolution may be quite
coarse (though this is rarely an issue for absolute times.)

If you are interested in measuring/calculating elapsed time, then
always use System.nanoTime(). On most systems it will give a
resolution on the order of microseconds. Be aware though, this call
can also take microseconds to execute on some platforms.

Clocks and Timers - General Overview by David Holmes

Since System.currentTimeMillis() is relying on the systems time of day clock, adjustments to the time are legitimate, in order to keep it on time.

What means adjustments here? Take for instance a look at the description of CLOCK_REALTIME from Linux:

System-wide clock that measures real (i.e., wall-clock) time.
Setting this clock requires appropriate privileges. This clock is
affected by discontinuous jumps in the system time (e.g., if the
system administrator manually changes the clock
), and by the
incremental adjustments performed by adjtime(3) and NTP.

Best approach for dealing with time measures?

You are focusing too much on the unimportant detail of the precision. If you want to measure/profile the execution of certain operations, you have to make sure that these operation run long enough to make the measurement unaffected by one-time artifacts, small differences in thread scheduling timing, garbage collection or HotSpot optimization. In most cases, if the differences become smaller than the millisecond scale, they are not useful to draw conclusions from them.

The more important aspect is whether the tools are designed for your task. System.currentTimeMillis() and all other wall-clock based APIs, whether they are based on currentTimeMillis() or not, are designed to give you a clock which is intended to be synchronized with Earth’s rotation and its path around the Sun, which loads it with the burden of Leap Seconds and other correction measures, not to speak of the fact that your computer’s clock may be out of sync with the wall clock anyway and get corrected, e.g. via NTP updates, in the worst case jumping right when you are trying to measure your elapsed time, perhaps even backwards.

In contrast, System.nanoTime() is designed to measure elapsed time (exactly what you want to do) and nothing else. Since its return value has an unspecified origin and may even be negative, only differences between two values returned by this method make any sense at all. You will find this even in the documentation:

The values returned by this method become meaningful only when the difference between two such values, obtained within the same instance of a Java virtual machine, is computed.

So when you want to measure and process the elapsed time of your method execution or transactions, System.nanoTime() is the way to go. Granted, it only provides a naked long value, but it isn’t clear what kind of API support you want. Since points of time are irrelevant and even distracting here, you’ll have a duration only, which you may convert to other time units or, if you want to use the new time API, you can create a Duration object using Duration.ofNanos(long), allowing you to add and subtract duration values and compare them, but there isn’t much more you could do. You must not mix them up with wall-clock or calendar based durations…

As a final note, the documentation is a bit imprecise about the limitation. If you are calculating the difference between two values returned by System.nanoTime(), a numerical overflow isn’t bad per se. Since the counter has an unspecified origin, the start value of your operation might be close to Long.MAX_VALUE whereas the end value is close to Long.MIN_VALUE because the JVM’s counter had an overflow. In this case, calculating the difference will cause another overflow, producing a correct value for the difference. But if you store that difference in a signed long, it can hold at most 2⁶³ nanoseconds, limiting the difference to max 292 years, but if you treat it as unsigned long, e.g. via Long.compareUnsigned and Long.toUnsignedString, you may handle even 2⁶⁴ nanoseconds duration, in other words you can measure up to 584 years of elapsed time this way, if your computer doesn’t break in-between…

Which one is recommended: Instant.now().toEpochMilli() or System.currentTimeMillis()

Both are fine. And neither is recommended except for a minority of purposes.

What do you need milliseconds since the epoch for?

In Java, we can have many different ways to get the current timestamp,

For current timestamp just use Instant.now(). No need to convert to milliseconds.

Many methods from the first years of Java, also many in the standard library, took a long number of milliseconds since the epoch as argument. However, today I would consider that old-fashioned. See if you can find — or create — or more modern method that takes for instance an Instant as argument instead. Go object-oriented and don’t use a primitive long. It will make your code clearer and more self-explanatory.

As Eliott Frisch said in a comment, if this is for measuring elapsed time, you may prefer the higher resolution of System.nanoTime().

If you do need milliseconds since the epoch

Assuming that you have good reasons for wanting a count of milliseconds since the epoch, …

which one is recommended: Instant.now().toEpochMilli() or
System.currentTimeMillis()[?]

Opinions differ. Some will say that you should use java.time, the modern date and time API, for all of your date and time work. This would imply Instant here. Unsg java.time is generally a good habit since the date and time classes from Java 1.0 and 1.1 (Date, Calendar, TimeZone, DateFormat, SimpleDateFormat and others) are poorly designed and now long outdated, certainly not any that we should use anymore. On the other hand I am not aware of any design problem with System.curremtTimeMillis() in particular (except what I mentioned above about using a long count of milliseconds at all, which obviously is intrinsic to both Instant.now().toEpochMilli() and System.currentTimeMillis()).

If there is a slight performance difference between the two, I have a hard time imagining the situation where this will matter.

Take the option that you find more readable and less surprising in your context.

Similar questions

  • JSR 310 :: System.currentTimeMillis() vs Instant.toEpochMilli() :: TimeZone
  • Java current time different values in api


Related Topics



Leave a reply



Submit