System.nanoTime() inaccurate?

Hi,

I'm trying to do some accurate timing over long periods. I require at least sub 5ms accuracy over a number of years. Because System.currentTimeMillis() is only accurate to the system accuracy (which on Windows could be around 55ms) I am using the nanosecond timer as an offset from a base value derived from System.currentTimeMillis().

In theory, this should all work, and does... but only approximately. I am finding that the nanoTime "drifts" out by approx 140000ns for every second of real time, when measured against the millisecond timer. Obviously it doesn't take long before this becomes a problem.

So it appears that a nanoTime() nanosecond is not actually a nanosecond (at least on Windows/Intel), but actually slightly less.

Anyone else noticed this? Is it a bug?

Can anyone suggest a decent platform-independent solution?

Cheers,

Chris.

[902 byte] By [chris0a] at [2007-10-2 18:22:18]
# 1

No interruptable system/platform is determinitic regarding time, including Java and the Java doc states this explicitly

Returns the current value of the most precise available system timer, in nanoseconds.

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 time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change. Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#nanoTime()

MartinS.a at 2007-7-13 19:42:57 > top of Java-index,Other Topics,Algorithms...
# 2

> ....sub 5ms accuracy over a

> number of years. ...

I believe if I saw that I would state that either the requirement was relaxed of that both of the following would be added to the requirements.

1. Only a real time platform is targettable.

2. Only verified target platforms, including OS version, are acceptable.

jschella at 2007-7-13 19:42:57 > top of Java-index,Other Topics,Algorithms...
# 3

Ignoring the possible issue in the rate of the nanosecond clock (which is based on the CPU clock frequency in Intel systems and probably many others) and the rate of the millisecond clock (which usually based on some realtime clock component clocked by an oscillator separate from that used by the CPU and subject to adjustments on a fairly frequent basis to remain in synch with an external time reference), I think what you are looking for is not feasible.

To provide an accuracy of 5ms in a period of 1 year, you need a time standard that is good to an accuracy of 1 part in approximately 6.3 billion. The crystal oscillators used in computers DO NOT have that kind of accuracy.

cmccorveya at 2007-7-13 19:42:57 > top of Java-index,Other Topics,Algorithms...
# 4

Running this little program:import java.text.DecimalFormat;

public class Test {

static final long billion = 1000 * 1000 * 1000;

static final DecimalFormat format = new DecimalFormat("#,###");

public static void main(String[] args) throws Exception {

for (int i = 0; i < 60; ++i) {

long millisStart = System.currentTimeMillis();

long nanosStart = System.nanoTime();

long nanosDiff = 0;

do {

nanosDiff = System.nanoTime() - nanosStart;

} while (nanosDiff < 10 * billion);

long millisDiff = System.currentTimeMillis() - millisStart;

System.out.println(format.format(millisDiff) + "ms versus " +

format.format(nanosDiff) + "ns vields diff of " +

format.format(((millisDiff * 1000000) - nanosDiff)) + "ns");

}

}

}

I get the following output:

9,983ms versus 10,000,000,559ns vields diff of -17,000,559ns

9,984ms versus 10,000,000,559ns vields diff of -16,000,559ns

9,973ms versus 10,000,000,279ns vields diff of -27,000,279ns

9,974ms versus 10,000,000,000ns vields diff of -26,000,000ns

9,983ms versus 10,000,000,000ns vields diff of -17,000,000ns

9,974ms versus 10,000,000,279ns vields diff of -26,000,279ns

9,993ms versus 10,000,000,279ns vields diff of -7,000,279ns

9,974ms versus 10,000,001,117ns vields diff of -26,001,117ns

9,983ms versus 10,000,000,559ns vields diff of -17,000,559ns

9,974ms versus 10,000,000,000ns vields diff of -26,000,000ns

9,983ms versus 10,000,587,784ns vields diff of -17,587,784ns

9,974ms versus 10,000,000,000ns vields diff of -26,000,000ns

9,983ms versus 10,000,000,000ns vields diff of -17,000,000ns

9,974ms versus 10,000,001,118ns vields diff of -26,001,118ns

9,984ms versus 10,000,000,838ns vields diff of -16,000,838ns

9,973ms versus 10,000,001,117ns vields diff of -27,001,117ns

9,994ms versus 10,000,000,838ns vields diff of -6,000,838ns

9,973ms versus 10,000,000,559ns vields diff of -27,000,559ns

9,984ms versus 10,000,000,559ns vields diff of -16,000,559ns

9,973ms versus 10,000,001,118ns vields diff of -27,001,118ns

9,984ms versus 10,000,000,558ns vields diff of -16,000,558ns

9,973ms versus 10,000,000,000ns vields diff of -27,000,000ns

9,984ms versus 10,000,205,613ns vields diff of -16,205,613ns

9,973ms versus 10,000,000,280ns vields diff of -27,000,280ns

9,984ms versus 10,000,001,118ns vields diff of -16,001,118ns

[SNIP]

This demonstrates a couple of issues. First, you can see the impact of the ~10ms quanta of the system clock which seems indicate that the rate difference in the millisecond and nanosecond clock source is roughtly 0.16% - with the nanosecond clock running faster than the system clock.

That's on my notebook computer - your results will vary.

cmccorveya at 2007-7-13 19:42:57 > top of Java-index,Other Topics,Algorithms...
# 5

There is probably not a software solution to your requirements. Why do you need this level of accurancy ? We may be able to offer alternatives.

Referencing a first statum time server would struggle to meet that level of accurancy and those typically use atomic clocks. You could consider getting a reference time from GPS, which is probably the most realistic method of getting accurate time.

MartinS.a at 2007-7-13 19:42:57 > top of Java-index,Other Topics,Algorithms...