Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is -System.nanoTime() + System.nanoTime() guaranteed to be >= 0?

Tags:

java

time

Hi all I have a piece of code which looks like this:

public class Test {
    public static void main(String args[]) {
        long a = System.currentTimeMillis(); // line 1
        long b = System.currentTimeMillis(); // line 2
        assert b - a >= 0;

        long y = System.nanoTime(); // line 5
        long z = System.nanoTime(); // line 6
    }
}

So IERS stated that the next leap second is to occur immediately after 30th June 2012 11:59.9.

I was wondering if I'm right to say that if line 1 is run at 0.9 seconds after 30th June 2012 11:59.9 turns 1st July 2012 00:00.0,

And line 2 is run at 0.1 second after line 1,

The result of b - a could be negative ? (-900 milliseconds)

If that's the case, is it true that if line 5 is run at 0.9 seconds after 30th June 2012 11:59.9 turns 1st July 2012 00:00.0,

And line 6 is run at 0.1 second after line 5,

The result of z - y could be negative ? (-900,000,000 nanoseconds?)

like image 983
Pacerier Avatar asked Jan 13 '12 16:01

Pacerier


2 Answers

System.nanoTime should be monotonically increasing -- if you have two calls to it, A and B, and A happens-before B, then A <= B. But in practice, you can actually observe nanoTime going "backwards."

nanoTime is determined by an internal counter on the CPU whose starting time is essentially arbitrary (which is why it can't be used to determine wall clock time). This can cause a problem in multi-core environment, since one core's internal timer may have a different starting point than another's. Hotspot tries to compensate for this, but it doesn't always succeed, so you can in fact see nanoTime ticking backwards in some situations.

There was a recent discussion about this on the concurrency-interest mailing list. See in particular this email which links to this bug report, and this email which talks about the workaround (which doesn't seem to work, though I'm not sure why). The bug report has a fair amount of detail.

like image 58
yshavit Avatar answered Oct 18 '22 09:10

yshavit


Am I right to say that if line 1 is run at 0.9 seconds after 30th June 2012 11:59.9 turns 1st July 2012 00:00.0,

If the clock is not adjusted, 0.9 seconds after 30th June 2012 11:59.9 is 1st July 2012 00:00.8

The result of b - a would be negative ?

The currentTimeMillis() is the time in milli-seconds since 1970. It doesn't reset at the start of the day. Or any time in your life time.

The result of z - y would be negative ?

nanoTime() is not the time since the start of the day either. On many JVMs/OSes its the number of nano-seconds since the CPU was last reset.


Not all OSes provide the same resolution. e.g. RHEL/Centos 5.x give only micro-second resolution. This means you can have many calls in a row give the same value (to the micro-second)

long a = System.currentTimeMillis(); // line 1
long b = System.currentTimeMillis(); // line 2
assert b - a >= 0;

This will go backwards whenever the time is corrected by turning it backwards. e.g. via NTP.

long y = System.nanoTime(); // line 5
long z = System.nanoTime(); // line 6

This will go backwards on systems with more than one socket which do no correct for the difference in the Time Stamp Counter in different sockets. e.g. if you are on Windows XP and have two Sockets you can see the difference jump by 4,000,000 forward or backward as it switch the thread between sockets.

like image 45
Peter Lawrey Avatar answered Oct 18 '22 10:10

Peter Lawrey