Tech Per

10 Aug

System.currentTimeMillis, System.nanoTime and Their Resolution

When reading about Robust Java Benchmarking, I came across some things I had not thought about myself. It turns out, that even though System.currentTimeMillis() has the unit of milliseconds, the precision with which the method can return, is quite different on various operating systems.

Brent Boyer explains that Windows XP has a granularity of 15 ms, while Linux with a 2.6 kernel have a much finer grained precision of 1 ms. For many purposes, I guess this is no problem. I know I have not had a problem with it before.

What I did not know is, that the System.nanoTime call (available from Java5 and on) should be the one used for timing intervals. In addition to being nano-based, this call does not work as a “wall clock” as System.currentTimeMillis() do, in that it only measures elapsed time in an interval. The System.currentTimeMillis() call tries to reflect a “wall clock” time, as milliseconds since January 1, 1970. If the clock is drifting or being set by tools like NTP daemons, this will skew the results of System.currentTimeMillis().

Coincidentally, I was reading a chapter on concurrency in Effective Java (2nd Edition) (The Java Series) by Joshua Bloch, in which he states:

For interval timing, always use System.nanoTime in preference to System.currentTimeMillis

I do still have my thoughts about these two methods. When I read the javadoc for the new System.nanoTime call, I do not really feel at ease using it:

…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….

Note the “perhaps in the future” and “values may be negative”. Hmmm!

This just goes to show, that it is really hard, to provide a virtual platform, that is supposed to look and act equal on all platforms.

5 Responses to “System.currentTimeMillis, System.nanoTime and Their Resolution”

  1. 1
    Shams Mahmood Says:

    If we are going to be using it for interval timing why is a negative return value a concern?

  2. 2
    Jos Hirth Says:

    The resolution of currentTimeMillies is 1msec on Linux and Mac (if you ignore ancient versions), 50-55 on Win9x, 10 on WinNT/Win2k, and 15 on WinXP.

    On Windows nanoTime uses QPC (query performance counter), which is the most fragile timer known to mankind. My old machine suffered from so called QPC-leaping for example. I.e. it randomly jumps a few seconds into the future if there is some load on the bus (e.g. if you display some graphics).

    All applications which relied on QPC were completely broken.

    Well, using it is alright for benchmarks which only need to work on one machine. Either way I strongly recommend to make your benchmarks run for at least a few seconds in order to get meaningful results.

    A more robust timer with a 1msec resolution is LWJGL’s Sys.getTime which uses TGT (time get time) on Windows and currentTimeMillis elsewhere. Only some ~20 year old machines have issues with TGT, which makes it the most sensible choice.

    All Quake engine based games are using TGT for example. That’s also the reason why they behave very bad as soon as 1000fps are reached, but obviously this isn’t really much of an issue.

  3. 3
    polesen Says:

    @Jos: Thank you for the pointer to Sys.getTime().

  4. 4
    polesen Says:

    @Shams:

    Isn’t it odd, if it returns a negative value on a request? I would interpret that as it saying, that a negative amount of time has elapsed since my last call.

  5. 5
    Shams Mahmood Says:

    @polesen

    yes it’s strange but when u will be subtracting numbers from two of your calls, you’ll still be ending up with a positive number

Leave a Reply

© 2008 Tech Per | Entries (RSS) and Comments (RSS)

GPS Reviews and news from GPS Gazettewordpress logo