16

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?)

Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • Are you asking if a leap second will change the way the monotonically increasing clock works? What do you expect to happen? – Edward Thomson Jan 13 '12 at 16:23
  • Why would these be negative? Have you found a way to go back in time? Unless the system clock is adjusted between those two calls, the times will be positive or null (depending on the accuracy of the system clock) – JB Nizet Jan 13 '12 at 16:25
  • @EdwardThomson Yes I was wondering if a leap second will affect the result of System.currentTimeMillis() since POSIX time goes **backwards** by one second everytime a leap second occur – Pacerier Jan 13 '12 at 16:27
  • 2
    @JBNizet Because POSIX time goes back in time whenever a leap second occur as shown in the table *Unix time across midnight when a UTC leap second is inserted* : http://en.wikipedia.org/wiki/Unix_time – Pacerier Jan 13 '12 at 16:30
  • 2
    Then why not ask *that* question rather than hoping people click on links and/or remember when the leap second is scheduled. ;) – Brian Roach Jan 13 '12 at 16:36
  • @BrianRoach I mean that's the question I wanted to ask in the first place, I'd thought its obvious that I had chosen such an exact date 30th June 2012 11:59.9 – Pacerier Jan 13 '12 at 16:39

5 Answers5

12

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.

yshavit
  • 42,327
  • 7
  • 87
  • 124
3

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • +1 for the socket thing. It's obviously against nanoTime()'s definition. I hope Windows XP is the only system that does this. – Joonas Pulakka Jan 13 '12 at 16:32
  • 2
    Windows Vista/7, Solaris and supported versions of Linux are all fine. I believe Linux had this bug once upon a time. – Peter Lawrey Jan 13 '12 at 16:37
  • 1
    @PeterLawrey But isn't the clock adjusted at the end of 30th June 2012 for the 2012 leap second ? If so, wouldn't that mean that we'd get a negative result? – Pacerier Jan 13 '12 at 16:41
  • It would mean when NTP kicks in (as most systems don't actually support UTC leap seconds) it might see that the time on the machine is 1 second fast. If you were to correct for this immediately you would see a jump in time as you suggest. However most systems don't do this, instead over a period of time say one minute, it adds 59 seconds (instead of 60 seconds) Instead of time going backwards, it goes slightly slow until its correct. The same thing happens to move forward by 1 second. Much larger corrections do result in a jump in time. http://www.manpagez.com/man/8/ntpdate/ – Peter Lawrey Jan 13 '12 at 16:45
  • @PeterLawrey However isn't the default (the one used on most systems) to step the time using `settimeofday(2)` if the offset is greater than +-128 ms? http://www.ntp.org/ntpfaq/NTP-s-algo.htm#Q-CLOCK-DISCIPLINE . If the default is to *smear* the leap second over a period of time already, Why did the guys at http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html still have to apply a *leap-smear* patch to do just that? – Pacerier Jan 14 '12 at 01:04
  • @Pacerier That a good point. I admit I haven't worked on a system which was production live on a midnight on new year's eve and it mattered. – Peter Lawrey Jan 14 '12 at 08:30
  • 1
    @Pacerier NTP communicates a leap second indicator to clients, and by default on Linux with `ntpd`, this is what results in a backward step of one second, rather than polling the NTP server and seeing that there is an error. So the step threshold of 128 ms isn't a factor unless you try to use something like Google or AWS "smeared" leap seconds, where the NTP client is dumb, but the server is patched to slew the time. Then, the polling interval needs to be small enough that it doesn't exceed 128 ms. That's why they smear over the whole day instead of 1000 seconds like UTC-SLS. – erickson Jul 25 '19 at 21:57
2

No, you are wrong. Because this is not millisecond part of current time, but total milliseconds passed from year 1970.

They could be the same, but later is not less than earlier. However, if a NTP daemon doing its job it could happen, if at some moment the system clock has been adjusted.

The nanoTime is more reliable way, since it doesn't depend on the system clock and should not be changed by clock adjustments.

kan
  • 28,279
  • 7
  • 71
  • 101
  • 1
    it's the POSIX time right? Because if it is the POSIX time, it **is not** the total milliseconds passed from year 1970. Leap seconds cause POSIX time to go backwards, so if its based on POSIX time, it will go backwards too – Pacerier Jan 13 '12 at 16:31
  • Leap seconds don't result in time going backwards when they are corrected for. Instead it results in an extra second being added over a period of time (AFAIK minutes) making the clock appear slightly slower than normal e.g. compared with nanoTime(). – Peter Lawrey Jan 13 '12 at 16:39
  • @PeterLawrey Sry I'm getting confused here. Isn't the chart at http://en.wikipedia.org/wiki/Unix_time#leapsecondinserted showing the UNIX time `915 148 800.75` going backwards to `915 148 800.00` ? – Pacerier Jan 13 '12 at 17:04
  • I doubt most UNIX systems are `strictly conforming POSIX.1 systems at the end of 1998` However, you could be right that leap seconds are handled differently to other time corrections. AFAIK, most systems have leap second turned off by default and allow NTP to correct the time, but I could be wrong about this. – Peter Lawrey Jan 13 '12 at 17:19
1

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

Yes. It's a timer, not any absolute time, and according to its docs, it Returns the current value of the most precise available system timer, in nanoseconds. The value returned represents nanoseconds since some fixed but arbitrary time. Time since some fixed time doesn't go backwards (although after 292 years the difference will overflow, but that's hardly a practical issue. Also, as Peter Lawrey pointed out, Windows XP has a bug that breaks nanotime's guarantees).

System.currentTimeMillis() is completely different. It returns absolute time (milliseconds since 1970) which is got from the computer's clock, which could be adjusted anytime.

Community
  • 1
  • 1
Joonas Pulakka
  • 36,252
  • 29
  • 106
  • 169
  • Do you mean to say that even if the the time is adjusted through NTP, `System.nanoTime()`'s time is stable? – Pacerier Jan 13 '12 at 16:45
  • @Pacerier: Yes, exactly. That's the idea of having `currentTimeMillis()` - if `nanoTime()` would behave similarly, then `currentTImeMillis()` would be redundant (just divide nanotime by 10e6). – Joonas Pulakka Jan 13 '12 at 16:48
  • 1
    @JoonasPulakka: While I agree with you about `nanoTime()`, I don't think you can use redundancy as an argument here, since `nanoTime()` was added in Java 5. (Even if that made `currentTimeMillis()` redundant, it would have been kept around even if to keep backcompat.) – Edward Thomson Jan 13 '12 at 18:11
1

My reading of the wiki page is same as yours: currentTimeMillis() can go backwards due to leap second.

(Why did they bring this fine astronomical problem into civil time? No civilian cares if solar noon is off by a few seconds; actually nobody uses local time to begin with; people in the same time zone can observer solar noon differ by 1 hour. and in a big country with no time zone, the difference can be hours.)

irreputable
  • 44,725
  • 9
  • 65
  • 93