Java: System.nanoTime vs System.currentTimeMillis

Pradeesh Kumar
4 min readDec 26, 2022
Photo by Aron Visuals on Unsplash

Introduction

You will see the following code snippet commonly in pretty much any codebase to measure the elapsed time.

long startTime = System.currentTimeMillis();
//... some actions
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;

System.out.println("Time taken to execute the code: " + elapsedTime);

Java offers two basic methods for measuring time value:System.currentTimeMillis() and System.nanoTime(). They can be used to measure the elapsed time: the amount of time that passes from the start of an event to the end. There are substantial differences between these two methods. Let’s explore them in this article.

The Basic Difference

  • System.currentTimeMillis() returns the current time in milliseconds.
  • System.nanoTime() returns the current time in nanoseconds.

Stability

  • The value returned by the methodSystem.currentTimeMillis() is tied to the system wall-clock time. Therefore, values are not guaranteed to be monotonically increasing. This means that if you change the system time while running the program, or the system time auto changes during day-light-saving, or NTP Time Server sync (internet time sync), this method will sync with the system clock and provide the latest updated time. The calculated elapsed time value can be negative while such time modification happens in the system. Hence this method can be non-monotonous.
  • In opposite to the above pointSystem.nanoTime() gives the monotonically increasing epoch from an arbitrary point since the start of the JVM. The returned value is not synced with the system wall clock. This means that any modification done to the system time such as a manual update or automatic update with NTP server or daylight saving time update, will not affect this method.

Example:

Mike wants to measure the amount of time taken to retrieve the user records from the database.

Suppose the current system time at this point is25th Dec 2022 7:30:00 0milliseconds

Using System.currentTimeMillis()

long startTime = System.currentTimeMillis();

//.. the code to retrieve users from a database
//.. suppose the system time synced to the internet time, changes to 25th Dec 2022 6:30:00

long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime)); // This value will be negative since someone changed the system time.

Using System.nanoTime()

long startTime = System.nanoTime();

//.. the code to retrieve users from a database
//.. suppose the system time synced to the internet time, changes to 25th Dec 2022 6:30:00

long endTime = System.nanoTime();
System.out.println("Elapsed time: " + (endTime - startTime)); // This will be positive and valid! The modification to the system time will not affect this.

Monotonicity

  • Since theSystem.currentTimeMillis() gives the time epoch tied to the system clock, we can compare the time returned by two different JVMS or even two different computers.
  • When you start the JVM, it sets an arbitrary point of time as a reference point(which may not be the current system time).System.nanoTime() returns the monotonically increased values from the reference point. Hence it doesn’t make any sense to compare the current nano time returned by two JVMs.

Granularity

  • System.currentTimeMillis()gives the finest possible granularity is 1 millisecond. It makes measuring anything shorter than 1 ms impossible. For example, many operating systems measure time in units of tens of milliseconds. Let’s say your OS measures time in chunks of 100ms. In this scenario, there is no way to measure anything that needs to be more precise than this. So if an operation takes somewhere between 20 and 80ms, your measurements are either 0 or 100ms.
  • System.nanoTime() gives the high-resolution time source in nanoseconds.

Which one should you use?

  • UsenanoTime to measure the time elapsed between two events, for example, a stopwatch. The result will be inaccurate or can be negative if you usecurrentTimeMillis .
  • UsenanoTime to render your scenes when you develop a game, to get a smooth animation. Suppose you want to achieve a 90Hz refresh rate, you won’t be able to achieve it currentTimeMillis since its accuracy is somewhere between 20 to 80ms depending on the system clock.
  • Use currentTimeMillis when you want to measure the exact time of an event started in two JVMs or two computers. Suppose you want to track the exact system time when the player started a game, currentTimeMillis gives you the epoch in sync with the current system time which is comparable if both the system are in sync with the latest internet time. nanoTime will give the rubbish result in such cases since each JVM sets a random time reference when they start, and the nanoTime method produces a monotonically increased value from that particular reference.

--

--

Pradeesh Kumar

Computer Science | Distributed Computing | Databases | Cloud