most accurate time type in java? - java

I want to compare the performance of certain operations in my application.
Other than using the Date object, is there anything more precise?

public static long nanoTime() - Returns the current value of the most precise available system timer, in nanoseconds.
As Zach Scrivener states in his answer:
My guess is that since System.nanoTime() uses the "most precise
available system timer" which apparently only has
millisecond-precision on your system, you can't get anything better.

If you're measuring elapsed time by subtracting two timestamps, you should use System.nanoTime() to get those timestamps. That's what it's for.

To get the CPU time you can use the getCurrentThreadCpuTime of the Thread Management Bean.
It returns the CPU time used by the actual thread in nanoseconds:
ThreadMXBean threadMX = ManagementFactory.getThreadMXBean();
long time = threadMX.getCurrentThreadCpuTime();
// do something
time = threadMX.getCurrentThreadCpuTime() - time; // CPU time in nanoseconds
check the documentation for details and some problems like CPU time measurement not being enabled.

Related

How to get current time in nano seconds in java?

I do lots of research but did not find any good answer.
I wanted to get the current date and time in a nanosecond.
I found that System.nanoTime() will provide nanoseconds, but that is and system elapsed time. means it will provide a time when system up. I need to use the current date and time in a nanosecond.
I need this for avoiding duplicate of points in InfluxDB, see How does InfluxDB handle duplicate points? So when I use millisecond I am facing issues of data union. So need deciding to go with nanosecond but the problem is while generated nano the second using System.nanoTime() did not contain current date and time data. and it give me JVM uptime which is useless for me.
In theory, it is possible to get the current time to "better than microsecond" accuracy as follows:
Clock clock = Clock.systemDefaultZone();
Instant instant = clock.instant(); // or Instant.now();
long seconds = instant.getEpochSecond();
long nano = instant.getNano();
// epoch nanoseconds = seconds * 10E9 + nano
The problems:
The systemDefaultZone() call gives the "best available clock" for the platform. The JVM spec says that this may have better than millisecond precision, but this is not guaranteed. So the nano value may have no better than millisecond precision.
The values of seconds and nano depend on the accuracy of the local hardware clock. On many systems, keeping the local clock synced to a "real" time is difficult. Often, sub-millisecond accuracy is challenging, and apparent nanosecond accuracy is an illusion.
Even you have previously managed to sync the hardware clock with a "real" time source to nanosecond accuracy, the overheads and variability in the making the above calls to acquire the epoch nanosecond time would swamp the hardware clock's nanosecond accuracy. Things like memory cache variability, how busy the main memory bus is, etc. And of course the hardware clock may have drifted since it was last synced externally.
In practice, on most systems, nano-second accuracy is unachievable, so you need avoid designs / algorithms that depend on this.
Finally, Thanks for Mr. Franz Wilhelmstötter
I found one solution. using http://jenetics.io/ and
Class call NanoClock.java is converting and doing the same trick that Stephen C suggested. I want to share this because it will useful for others as well. I am not able to confirm that is given precise nano time, but this trick works for me. #Ole V.V. Thanks again for your help.
You get the best accuracy and precision Java can give you from Instant.now(). Whether this is enough to solve your problem, I dare not tell. Certainly on a normal computer there is no way to get nanosecond accuracy.
You may need to play some tricks with adding an artificial nanosecond in case Instant.now() returns the same value twice.
Or simple use the trick mentioned in your link:
Introduce an arbitrary new tag to enforce uniqueness.
For the trick of adding an artificial nanosecond you may for example use something like the following:
public class TimeProvider {
Instant last = Instant.now().minusSeconds(1);
Instant getUniqueInstant() {
Instant result = Instant.now();
if (! result.isAfter(last)) {
result = last.plusNanos(1);
}
last = result;
return result;
}
}
When I draw times in rapid succession from this class on my computer, I get results like below. It would seem from the output (the way I interpret it):
My JVM cannot get higher precision than microseconds (6 decimals on the seconds) from the system clock.
An artificial nanosecond is added now and then to keep the instants unique.
.
2018-08-29T15:18:35.617616001Z
2018-08-29T15:18:35.617617Z
2018-08-29T15:18:35.617618Z
2018-08-29T15:18:35.617618001Z
2018-08-29T15:18:35.617619Z
2018-08-29T15:18:35.617619001Z
2018-08-29T15:18:35.617620Z
2018-08-29T15:18:35.617620001Z
2018-08-29T15:18:35.617621Z
2018-08-29T15:18:35.617621001Z
2018-08-29T15:18:35.617622Z
2018-08-29T15:18:35.617623Z
2018-08-29T15:18:35.617623001Z
2018-08-29T15:18:35.617624Z
2018-08-29T15:18:35.617624001Z
2018-08-29T15:18:35.617625Z
2018-08-29T15:18:35.617625001Z
2018-08-29T15:18:35.617626Z
2018-08-29T15:18:35.617626001Z
2018-08-29T15:18:35.617627Z
2018-08-29T15:18:35.617627001Z
2018-08-29T15:18:35.617628Z
2018-08-29T15:18:35.617631Z
2018-08-29T15:18:35.617634Z
2018-08-29T15:18:35.617635Z
2018-08-29T15:18:35.617636Z
2018-08-29T15:18:35.617636001Z
2018-08-29T15:18:35.617637Z
2018-08-29T15:18:35.617637001Z
2018-08-29T15:18:35.617638Z

What is the current state of affairs in the world of Java timers?

From time to time I encounter mentions of System.nanoTime() being a lot slower (the call could cost up to microseconds) than System.currentTimeMillis(), but prooflinks are often outdated, or lead to some fairly opinionated blog posts that can't be really trusted, or contain information pertaining to specific platform, or this, or that and so on.
I didn't run benchmarks since I'm being realistic about my ability to conduct an experiment concerning such a sensitive matter, but my conditions are really well-defined, so I'm expecting quite a simple answer.
So, on an average 64-bit Linux (implying 64-bit JRE), Java 8 and a modern hardware, will switching to nanoTime() cost me that microseconds to call? Should I stay with currentTimeMillis()?
As always, it depends on what you're using it for. Since others are bashing nanoTime, I'll put a plug in for it. I exclusively use nanoTime to measure elapsed time in production code.
I shy away from currentTimeMillis in production because I typically need a clock that doesn't jump backwards and forwards around like the wall clock can (and does). This is critical in my systems which use important timer-based decisions. nanoTime should be monotonically increasing at the rate you'd expect.
In fact, one of my co-workers says "currentTimeMillis is only useful for human entertainment," (such as the time in debug logs, or displayed on a website) because it cannot be trusted to measure elapsed time.
But really, we try not to use time as much as possible, and attempt to keep time out of our protocols; then we try to use logical clocks; and finally if absolutely necessary, we use durations based on nanoTime.
Update: There is one place where we use currentTimeMillis as a sanity check when connecting two hosts, but we're checking if the hosts' clocks are more than 5 minutes apart.
If you are currently using currentTimeMillis() and are happy with the resolution, then you definitely shouldn't change.
According the javadoc:
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 {#link #currentTimeMillis()}.
So depending on the OS implementation, there is no guarantee that the nano time returned is even correct! It's just the 9 digits long and has the same number of millis as currentTimeMillis().
A perfectly valid implementation could be currentTimeMillis() * 1000000
Therefore, I don't think you really gain a benefit from nano seconds even if there wasn't a performance issue.
I want to stress that even if the calls would be very cheap, you will not get the nanosecond resolution of your measurements.
Let me give you an example (code from http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--):
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
So while both long values will be resolved to a nanosecond, JVM is not giving you a guarantee that every call you make to nanoTime(), JVM will give you a new value.
To illustrate this, I wrote a simple program and ran it on Win7x64 (feel free to run it and report the results as well):
package testNano;
public class Main {
public static void main(String[] args) {
long attempts = 10_000_000L;
long stale = 0;
long prevTime;
for (int i = 0; i < attempts; i++) {
prevTime = System.nanoTime();
long nanoTime = System.nanoTime();
if (prevTime == nanoTime) stale++;
}
System.out.format("nanoTime() returned stale value in %d out of %d tests%n", stale, attempts);
}
}
It prints out nanoTime() returned stale value in 9117171 out of 10000000 tests.
EDIT
I also recommend to read the Oracle article on this: https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks. The conclusions of the article are:
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.
Also you might find this discussion interesting: Why is System.nanoTime() way slower (in performance) than System.currentTimeMillis()?.
Running this very simple test:
public static void main(String[] args) {
// Warmup loops
long l;
for (int i=0;i<1000000;i++) {
l = System.currentTimeMillis();
}
for (int i=0;i<1000000;i++) {
l = System.nanoTime();
}
// Full loops
long start = System.nanoTime();
for (int i=0;i<10000000;i++) {
l = System.currentTimeMillis();
}
start = System.nanoTime()-start;
System.err.println("System.currentTimeMillis() "+start/1000);
start = System.nanoTime();
for (int i=0;i<10000000;i++) {
l = System.nanoTime();
}
start = System.nanoTime()-start;
System.err.println("System.nanoTime() "+start/1000);
}
On Windows 7 this shows millis to be just over 2 times as fast:
System.currentTimeMillis() 138615
System.nanoTime() 299575
On other platforms, the difference isn't as large, with nanoTime() actually being slightly (~10%) faster:
On OS X:
System.currentTimeMillis() 463065
System.nanoTime() 432896
On Linux with OpenJDK:
System.currentTimeMillis() 352722
System.nanoTime() 312960
Well the best thing to do in such situations is always to benchmark it. And since the timing depends solely on your platform and OS there's really nothing we can do for you here, particularly since you nowhere explain what you actually use the timer for.
Neither nanoTime nor currentTimeMillis generally guarantee monotonicity (nanoTime does on HotSpot for Solaris only and otherwise relies on an existing monotone time source of the OS - so for most people it will be monotonic even if currentTimeMillis is not).
Luckily for you writing benchmarks in Java is relatively easy these days thanks to jmh (java measuring harness) and even luckier for you Aleksey Shipilёv actually investigated nanoTime a while ago: See here - including source code to do the interesting benchmarking yourself (it's also a nice primer to jmh itself, if you want to write accurate benchmarks with only relatively little knowledge - that's the one to pick.. just amazing how far the engineers behind that project went to make benchmarking as straight-forward as possible to the general populace! Although you certainly can still fuck up if you're not careful ;-))
To summarize the results for a modern linux distribution or Solaris and a x86 CPU:
Precision: 30ns
Latency: 30ns best case
Windows:
Precision: Hugely variable, 370ns to 15 µs
Latency: Hugely variable, 15ns to 15 µs
But note Windows is also known to give you a precision of up to 100ms for currentTimeMillis in some rare situations soo.. pick your poison.
Mac OS X:
Precision: 1µs
Latency: 50ns
Be vary these results will differ greatly depending on your used platform (CPU/MB - there are some interesting older hardware combinations around, although they're luckily getting older) and OS. Heck obviously just running this on a 800 MHz CPU your results will be rather different when compared to a 3.6GHz server.

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

Given the following Java code:
class Tester
{
public static void main(String[] args)
{
System.out.println((System.nanoTime()/1000));
System.out.println(System.currentTimeMillis());
}
}
It gave an output of
2626051678558
1377785791569
I was expecting a little difference between the two but I was wrong.
Do you have any idea guys why it behaved like that?
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.
long currentTimeMillis = System.currentTimeMillis();
long nanos = TimeUnit.MILLISECONDS.toNanos(currentTimeMillis);
System.out.println(nanos);
System.out.println(TimeUnit.NANOSECONDS.toMillis(nanos)*1000000);
nanoTime(), as the java doc says, is a precision timer. currentTimeMillis() is NOT A TIMER, it is the "wall clock". nanoTime() will always produce positive elapsed time, currentTimeMillis will not (e.g. if you change the date, hit a leap second, etc.)
If you're on Android, nanoTime is affected by deep sleep modes. Use SystemClock.elapsedRealtime() (which returns msec) instead

java - system.nanoTime() runs too slow

I am using system.nanoTime in my app and I calculate time relative to a starttime.
My app ran very well until I copied it to a new computer and on it the nano time gives me slower values.
I wrote a simple app just to make sure.
the nano time is compared to the system time.
It shows the same values in other computers except my new one . any suggestions?
Here is my code:
First I have
private long initNanoTime = System.nanoTime();
private long initTime = System.currentTimeMillis();
than I loop a thread that runs every second:
long timeUsingNanoTime = initTime + (System.nanoTime() - initNanoTime) / 1000000;
long timeUsingMilis = System.currentTimeMillis();
long nanotimeOffset = Math.abs(timeUsingNanoTime - timeUsingMilis);
if (nanotimeOffset < 100l) ? print("close") : print(far);
Edit : I am using nano because I need to handle even ts that occur in nano time and print to a log the nano time which it was received in
It's like the Java API docs say about System.nanoTime():
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.
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().
It does not provide any coupling with the timestamp (currentTimeMillis) and does not provide a fixed resolution.
In your case it seems that Java now has a higher resolution timer available than before, and so does not need to use the system time.

Time taken to execute a java method is zero?

I am reading the system time just before the method is invoked and immediately after method returns and taking the time difference, which will give the time taken by a method for execution.
Code snippet
long start = System.currentTimeMillis ();
method ();
long end = System.currentTimeMillis ();
System.out.println ("Time taken for execution is " + (end - start));
The strange thing is the output is 0..how is this possible..?
Chances are it's taking a shorter time than the fairly coarse-grained system clock. (For example, you may find that System.currentTimeMillis() only changes every 10 or 15 milliseconds.)
System.currentTimeMillis is good for finding out the current time, but it's not fine-grained enough for measuring short durations. Instead, you should use System.nanoTime() which uses a high-resolution timer. nanoTime() is not suitable for finding the current time - but it's designed for measuring durations.
Think of it as being the difference between a wall clock and a stopwatch.
use nanoTime()
Because it took less than 1 millisecond?
If you want to get a more meaningful metric, I would suggest calling your method in a loop 1000000 times, timing that, and then dividing by 1000000.
Of course, even then, that might not be representative; the effects on the cache will be different, etc.

Categories

Resources