0

I just found System.currentTimeMillis is not accurate on windows XP, now I tried System.nanoTime() with the same code.

Since 1ms = 1,000,000ns, so I think the result should be 15,000,000ns, but it's not.

See the sample code:

public class NanoTime {
    public static void main(String[] args) {
        long start = 0;
        long end = 0;
        while (true) {
            if (start == 0) {
                start = System.nanoTime();
            } else {
                long current = System.nanoTime();
                if (current != start) {
                    end = current;
                    break;
                }
            }
        }
        System.out.println("The time interval of your OS: " + (end - start) + "ns");
    }
}

The result is:

The time interval of your OS: 655ns

Seems it's much better than System.currentTimeMillis(). But why? Can we believe this result?

Community
  • 1
  • 1
Freewind
  • 193,756
  • 157
  • 432
  • 708

3 Answers3

4

Why?

Because it's not trying to be accurate in the same way.

From the Javadocs:

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time.

So yes, it's good for measuring elapsed time accurately. It's not good at giving you an absolute time, and you won't get that more accurately than System.currentTimeMillis(), at least without coordinating explicitly with NTP etc. Use the right tool for the job, and don't design a system which needs a hugely accurate absolute time.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • thanks again. So there is no difference if we use `nanotime` or `millistime` to measure the elapsed time? The result `655ns` doesn't mean `0.000655ms`? – Freewind Oct 22 '11 at 11:19
  • 2
    @Freewind: No, there's a big difference. If you want to measure *elapsed time*, you *should* use `nanotime`, because it's more accurate than `currentTimeMillis`. You use `currentTimeMillis` for *absolute* times. As I say, use each method for what it was designed for. – Jon Skeet Oct 22 '11 at 11:31
4

If your Windows XP has SP3 then you can believe that result... on Windows the JVM implements nanoTime() internally using QueryPerformanceCounter/QueryPerformanceFrequency API which is basically located in HAL (Hardware abstraction layer) and uses some CPU-internal interval instructions which are rather accurate... it is only good for interval measurements NOT for time handling...

For a more elaborate description see http://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks and http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html

EDIT - as per comment:

The above mentioned function are used by the JVM itself internally when nanoTime is called which has absolutely NOTHING to do with JNI - they are not exposed to Java code!

EDIT 2 - as per comments:

nanoTime() is the right tool to measure elapsed time accurately while currentTimeMillis is the right tool to handle absolute time.

Yahia
  • 69,653
  • 9
  • 115
  • 144
  • 1
    Which are both not avaliable in Java unless using JNI – Brett Walker Oct 22 '11 at 11:10
  • 1
    the JVM uses them INTERNALLY when you call `nanoTime()`! – Yahia Oct 22 '11 at 11:12
  • @Yahia, thank you, your answer is different from JonSkeet's, I don't know should I believe it or not -_-## – Freewind Oct 22 '11 at 11:23
  • Per your answer, we should always use `System.nanoTime()` if we want a accurate elapsed time which may be less than `10ms`? – Freewind Oct 22 '11 at 11:24
  • 1
    @Freewind where do you see the difference ? In my answer I explain why it is technically accurate while Jon Skeet writes that it good to "measuring elapsed time (not absolute time)" which is the same I write (i.e. interval measurement)... – Yahia Oct 22 '11 at 11:25
  • @Freewind Jon Skeet writes that `nanoTime` is good for measuring elapsed time accurately - same as I write... follow the links in my answer and see for yourself what Oracle writes about this – Yahia Oct 22 '11 at 11:26
  • My misunderstanding, sorry. I think I understand now. If the elapsed time is huge, that we can use both "System.currentTimeMillis" and "nanoTime". If it's small (less than 10ms), we'd better use `nanoTime`. And the result of `655ns` is accurate enough, we can trust it's really `665ns` – Freewind Oct 22 '11 at 11:32
  • yes... see the comment from Jon Skeet below... he clarifies and writes the same... – Yahia Oct 22 '11 at 11:33
0

The best way to know what a method does is to read its javadoc. Not to guess what it does using experiments.

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255