Skip to main content

Is System.nanoTime() completely useless?



As documented here , on x86 systems. Java's System.nanoTime() returns the time value using a cpu specific counter. Now consider the following case I use to measure time of a call -







long time1= System.nanotime();

foo();

long time2 = System.nanotime();

long timeSpent = time2-time1;







Now in a multi core system, it could be that after measuring time1, the thread is scheduled to a different processor whose counter is less than that of the previous cpu. Thus we could get a value in time2 which is less than time1. Thus we would get a negative value in timeSpent.





Considering this case, isnt it that System.nanotime is pretty much useless for now?





Edit: I know that changing the system time doesnt affect nanotime. that is not the problem i describe above. The problem is that each cpu will keep a different counter since it was turned on. This counter can be lower on the 2nd cpu compared to the first cpu. Since the thread can be scheduled by the OS to the 2nd cpu after getting time1, the value of timeSpent may be incorrect and even negative.


Comments

  1. That post is wrong, and nanoTime is safe. There's a comment on the post which links to a blog post by David Holmes, a realtime and concurrency guy at Sun. It says:


    System.nanoTime() is implemented using the QueryPerformanceCounter/QueryPerformanceFrequency API [...] The default mechanism used by QPC is determined by the Hardware Abstraction layer(HAL) [...] This default changes not only across hardware but also across OS versions. For example Windows XP Service Pack 2 changed things to use the power management timer (PMTimer) rather than the processor timestamp-counter (TSC) due to problems with the TSC not being synchronized on different processors in SMP systems, and due the fact its frequency can vary (and hence its relationship to elapsed time) based on power-management settings.


    So, on Windows, this was a problem up until WinXP SP2, but it isn't now.

    I can't find a part II (or more) that talks about other platforms, but that article does include a remark that Linux has encountered and solved the same problem in the same way, with a link to the FAQ for clock_gettime(CLOCK_REALTIME), which says:



    Is clock_gettime(CLOCK_REALTIME) consistent across all processors/cores? (Does arch matter? e.g. ppc, arm, x86, amd64, sparc).


    It should or it's considered buggy.

    However, on x86/x86_64, it is possible to see unsynced or variable freq TSCs cause time inconsistencies. 2.4 kernels really had no protection against this, and early 2.6 kernels didn't do too well here either. As of 2.6.18 and up the logic for detecting this is better and we'll usually fall back to a safe clocksource.

    ppc always has a synced timebase, so that shouldn't be an issue.


    So, if Holmes's link can be read as implying that nanoTime calls clock_gettime(CLOCK_REALTIME), then it's safe-ish as of kernel 2.6.18 on x86, and always on PowerPC (because IBM and Motorola, unlike Intel, actually know how to design microprocessors).

    There's no mention of SPARC or Solaris, sadly. And of course, we have no idea what IBM JVMs do. But Sun JVMs on modern Windows and Linux get this right.

    ReplyDelete
  2. I did a bit of searching and found that if one is being pedantic then yes it might be considered useless...in particular situations...it depends on how time sensitive your requirements are...

    Check out this quote from the Java Sun site:


    The real-time clock and
    System.nanoTime() are both based on
    the same system call and thus the same
    clock.

    With Java RTS, all time-based APIs
    (for example, Timers, Periodic
    Threads, Deadline Monitoring, and so
    forth) are based on the
    high-resolution timer. And, together
    with real-time priorities, they can
    ensure that the appropriate code will
    be executed at the right time for
    real-time constraints. In contrast,
    ordinary Java SE APIs offer just a few
    methods capable of handling
    high-resolution times, with no
    guarantee of execution at a given
    time. Using System.nanoTime() between
    various points in the code to perform
    elapsed time measurements should
    always be accurate.


    Java also has a caveat for the nanoTime() method:


    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.3 years (263
    nanoseconds) will not accurately
    compute elapsed time due to numerical
    overflow.


    It would seem that the only conclusion that can be drawn is that nanoTime() cannot be relied upon as an accurate value. As such, if you do not need to measure times that are mere nano seconds apart then this method is good enough even if the resulting returned value is negative. However, if you're needing higher precision, they appear to recommend that you use JAVA RTS.

    So to answer your question...no nanoTime() is not useless....its just not the most prudent method to use in every situation.

    ReplyDelete
  3. No need to debate, just use the source.
    Here, SE 6 for Linux, make your own conclusions:

    jlong os::javaTimeMillis() {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
    }


    jlong os::javaTimeNanos() {
    if (Linux::supports_monotonic_clock()) {
    struct timespec tp;
    int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
    assert(status == 0, "gettime error");
    jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
    return result;
    } else {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);
    return 1000 * usecs;
    }
    }

    ReplyDelete
  4. You might like this better:

    http://juliusdavies.ca/nanotime/

    But it copies a DLL or Unix .so (shared object) file into the current user's home directory so that it can call JNI.

    Some background information is on my site at:

    http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html

    ReplyDelete
  5. This doesn't seem to be a problem on a Core 2 Duo running Windows XP and JRE 1.5.0_06.

    In a test with three threads I don't see System.nanoTime() going backwards. The processors are both busy, and threads go to sleep occasionally to provoke moving threads around.

    [EDIT] I would guess that it only happens on physically separate processors, i.e. that the counters are synchronized for multiple cores on the same die.

    ReplyDelete
  6. No its not..it just depends on your CPU, check High Precision Event Timer for how/why things are differently treated according to CPU.

    Basically, read the source of your Java and check what your version does with the function, and if it works against the cpu you will be running it on.

    IBM even suggests you use it for performance benchmarking. (2008 post but updated)

    ReplyDelete
  7. Linux corrects for discrepancies between CPUs, but windows does not.

    I suggest you assume System.nanoTime() is only accurate to around 1 micro-second.

    A simple way to get a longer timing is to call foo() 1000 or more times and divide the time by 1000

    ReplyDelete
  8. I have seen a negative elapsed time reported from using System.nanoTime(). To be clear, the code in question is:

    long startNanos = System.nanoTime();

    Object returnValue = joinPoint.proceed();

    long elapsedNanos = System.nanoTime() - startNanos;


    and variable 'elapsedNanos' had a negative value. (I'm positive that the intermediate call took less than 293 years as well, which is the overflow point for nanos stored in longs :)

    This occurred using an IBM v1.5 JRE 64bit on IBM P690 (multi-core) hardware running AIX. I've only seen this error occur once, so it seems extremely rare. I do not know the cause - is it a hardware-specific issue, a JVM defect - I don't know. I also don't know the implications for the accuracy of nanoTime() in general.

    To answer the original question, I don't think nanoTime is useless - it provides sub-millisecond timing, but there is an actual (not just theoretical) risk of it being inaccurate which you need to take into account.

    ReplyDelete
  9. Java is crossplatform, and nanoTime is platform-dependent. If you use Java - when don't use nanoTime. I found real bugs across different jvm implementations with this function.

    ReplyDelete
  10. Your question boils down to "did the guys who implemented the JVM for the box I am using implement this system function correctly".

    The answer is "Geez, one would hope so!".

    Having said that, if System.nanoTime in fact does glitch on muti-core machines, it wouldn't be the first JVM bug requiring a fix.

    ReplyDelete
  11. Absolutely not useless. Timing aficionados correctly point out the multi-core problem, but in real-word applications it is often radically better than currentTimeMillis().

    When calculating graphics positions in frame refreshes nanoTime() leads to MUCH smoother motion in my program.

    And I only test on multi-core machines.

    ReplyDelete
  12. The Java 5 documentation also recommends using this method for the same purpose.


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


    Java 5 API Doc

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex