Calculating time difference in Milliseconds - java

I am making a call to a method by passing ipAddress and it will return back the location of ipAddress like Country, City, etc etc. So I was trying to see how much time it is taking for each call. So I set the start_time before making call to method and end_time after making a call. So sometimes I get difference as 0. And resp contains the valid response.
long start_time = System.currentTimeMillis();
resp = GeoLocationService.getLocationIp(ipAddress);
long end_time = System.currentTimeMillis();
long difference = end_time-start_time;
So that means sometimes it is taking 0 ms to get the response back. Any suggestions will be appreciated.

Try this
long start_time = System.nanoTime();
resp = GeoLocationService.getLocationByIp(ipAddress);
long end_time = System.nanoTime();
double difference = (end_time - start_time) / 1e6;

I pretty much like the (relatively) new java.time library: it's close to awesome, imho.
You can calculate a duration between two instants this way:
import java.time.*
Instant before = Instant.now();
// do stuff
Instant after = Instant.now();
long delta = Duration.between(before, after).toMillis(); // .toWhatsoever()
API is awesome, highly readable and intuitive.
Classes are thread-safe too. !
References: Oracle Tutorial, Java Magazine

No, it doesn't mean it's taking 0ms - it shows it's taking a smaller amount of time than you can measure with currentTimeMillis(). That may well be 10ms or 15ms. It's not a good method to call for timing; it's more appropriate for getting the current time.
To measure how long something takes, consider using System.nanoTime instead. The important point here isn't that the precision is greater, but that the resolution will be greater... but only when used to measure the time between two calls. It must not be used as a "wall clock".
Note that even System.nanoTime just uses "the most accurate timer on your system" - it's worth measuring how fine-grained that is. You can do that like this:
public class Test {
public static void main(String[] args) throws Exception {
long[] differences = new long[5];
long previous = System.nanoTime();
for (int i = 0; i < 5; i++) {
long current;
while ((current = System.nanoTime()) == previous) {
// Do nothing...
}
differences[i] = current - previous;
previous = current;
}
for (long difference : differences) {
System.out.println(difference);
}
}
}
On my machine that shows differences of about 466 nanoseconds... so I can't possibly expect to measure the time taken for something quicker than that. (And other times may well be roughly multiples of that amount of time.)

Since Java 1.5, you can get a more precise time value with System.nanoTime(), which obviously returns nanoseconds instead.
There is probably some caching going on in the instances when you get an immediate result.

From Java 8 onward you can try the following:
import java.time.*;
import java.time.temporal.ChronoUnit;
Instant start_time = Instant.now();
// Your code
Instant stop_time = Instant.now();
System.out.println(Duration.between(start_time, stop_time).toMillis());
//or
System.out.println(ChronoUnit.MILLIS.between(start_time, stop_time));

I do not know how does your PersonalizationGeoLocationServiceClientHelper works. Probably it performs some sort of caching, so requests for the same IP address may return extremely fast.

In the old days (you know, anytime before yesterday) a PC's BIOS timer would "tick" at a certain interval. That interval would be on the order of 12 milliseconds. Thus, it's quite easy to perform two consecutive calls to get the time and have them return a difference of zero. This only means that the timer didn't "tick" between your two calls. Try getting the time in a loop and displaying the values to the console. If your PC and display are fast enough, you'll see that time jumps, making it look as though it's quantized! (Einstein would be upset!) Newer PCs also have a high resolution timer. I'd imagine that nanoTime() uses the high resolution timer.

In such a small cases where difference is less than 0 milliseconds you can get difference in nano seconds as well.
System.nanoTime()

You can use
System.nanoTime();
To get the result in readable format, use
TimeUnit.MILLISECONDS or NANOSECONDS

Related

timestamp milliseconds distinction in Dao operation

I have this realy simple dao operation which works pretty fine(part of a JUnit test):
for (int i = 0 ; i < 5000 ; i++)
mUserDao.saveUser(lUser, new Date().getTime());
the second parameter is a timestamp as long value. I test a kind of bulk save.
my question is: is it theoretical possible that I have two entries with the same long value in my database(mysql)? - in the same process.
A first look inside the relation shows me different long values for each entrie(At least the last millisecond is increased).
Thx in advance
Stefan
You can't guarantee that new Date() will give you the current time accurately. Often it can be wrong by up to about 10ms. Calling new Date() uses System.currentTimeMillis(). The Javadoc for currentTimeMillis() says
Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
So it's OS dependent. My experience is that Windows is particularly bad at giving you accurate dates.
And you certainly can't guarantee that you'll get different dates from successive calls to new Date().
Yes this is possible especially if you are having a fast hardware and that two saving operations are done in the same time. Then both created entries will have the same Long value.
I think milliseconds since the UNIX epoch are still the best way to measure time in a reasonably accurate way. However, it's not really good to have a timestamp only as a primary key. As long as you have a unique primary key you don't really need unique timestamps.
In case for some reason you still want the timestamp to be unique, you can apply an 'artificial smear'. For example:
long last = 0;
for (int i = 0 ; i < 5000 ; i++) {
long now = new Date().getTime();
if (now <= last) {
now = last + 1;
}
last = now;
mUserDao.saveUser(lUser, now);
}
There are many ways this can be improved but the code above is just to illustrate the idea of a smear.

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.

Creating a unique timestamp in Java

I need to create a timestamp (in milliseconds) in Java that is guaranteed to be unique in that particular VM-instance. I.e. need some way to throttle the throughput of System.currentTimeMillis() so that it returns at most one results every ms. Any ideas on how to implement that?
This will give a time as close the current time as possible without duplicates.
private static final AtomicLong LAST_TIME_MS = new AtomicLong();
public static long uniqueCurrentTimeMS() {
long now = System.currentTimeMillis();
while(true) {
long lastTime = LAST_TIME_MS.get();
if (lastTime >= now)
now = lastTime+1;
if (LAST_TIME_MS.compareAndSet(lastTime, now))
return now;
}
}
One way to avoid the limitation of one id per milli-second is to use a micro-second timestamp. i.e. multiply currentTimeMS by 1000. This will allow 1000 ids per milli-second.
Note: if time goes backwards, eg due to an NTP correction, the time will just progress at 1 milli-second per invocation until time catches up. ;)
You can use System.nanoTime() for better accuracy
Although I tried below and each time it gives different values, it probably is not guaranteed to be unique all the time.
public static void main(String[] args) {
long time1 = System.nanoTime();
long time2 = System.nanoTime();
long time3 = System.nanoTime();
System.out.println(time1);
System.out.println(time2);
System.out.println(time3);
}
Another way is to use AtomicInteger/AtomicLong classes for unique numbers if the time is not important for you and you just need unique number, this probably is a btter choice.
While searching for a solution I came across ULIB
(Universally Unique Lexicographically Sortable Identifier)
https://github.com/huxi/sulky/tree/master/sulky-ulid/
It's not a long, but shorter then UUID.
A ULID:
Is compatible with UUID/GUID's
1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
Lexicographically sortable
Canonically encoded as a 26 character string, as opposed to the 36 character UUID
Uses Crockford's base32 for better efficiency and readability (5 bits per character)
Case insensitive
No special characters (URL safe)
You could use System.nanoTime(), which is the most precise available system timer, and divide that by million to get milliseconds. While there are no formal guarantees on how often it's updated, I believe it's reasonable to assume that it updates way more (order(s) of magnitude) frequently than once per millisecond. Of course, if you create integer timestamps by less than millisecond interval, then they can't all be unique.
Note that the absolute value nanoTime() is arbitrary. If you want absolute time, calibrate it somehow, i.e. compare it to currentTimeMillis() when starting.
Could you perhaps make use of java.util.UUID and it's timestamp() and clockSequence()?
Method Summary
int clockSequence()
The clock sequence value associated with this UUID.
long timestamp()
The timestamp value associated with this UUID.
More details here: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html

Java: What is the unit of the difference of two System.currentTimeMillis?

What is the unit of the difference of two System.currentTimeMillis ?
start = System.currentTimeMillis();
longoperation();
elapsedTime = System.currentTimeMillis() - start;
What is the unit of elapsed time here. It doesn't look like milliseconds.
Is the above code segment the right way to find the time taken to execute longoperation()?
Yes, it is in milliseconds. Bear in mind that the difference is not absolutely correct and may vary.
It is ms (MiliSecond) only, you are doing right.
You can ignore time taken while calculating millis
It is milliseconds and your code looks correct.
Whatever you are doing is correct. If you want the time in seconds, simply divide it by 1000.
long start = System.currentTimeMillis();
longoperation();
long elapsedTime = (System.currentTimeMillis() - start)/1000;
Yes, currentTimeMillis() returns you a milliseconds value.
On Windows, it used to be the case that the returned value had quite low resolution, and so was only accurate to something like 10ms. I'm not certain whether this is still the case as I haven't used Windows for a few years - but if your longoperation() actually takes just a few millis, and you're running on Windows, then you may see elapsedTime variously being 10ms or 0ms.

Categories

Resources