0

I'm trying to see how long a snippet of codes takes to execute, however, as mentioned in the title, I get a negative value returned in the terminal.

I've searched stack overflow for this problem, and there were multiple questions the exact same of mine (1) (2), and all of them had the same answers: The clock counters on the different CPU cores could slightly differ from each other, resulting in this strange behavior.

However, these answers were from back in 2010, and since then both windows and java have developed a lot. Since this issue was already fixed back in 2010 on linux, I thought maybe this was also fixed on windows 10 now and my issue might come from a different problem.

That's why I've created this new thread, since there might be a new/different solution.

I'm using windows 10 and openjdk-19, and am using the following code

import java.sql.Timestamp;

public class Main
{
    public static void main(String[] args)
    {
        // gets the time in the beginning
        Timestamp begin = new Timestamp(System.currentTimeMillis());
        // assigns the number of iterations in the for loop and o to zero
        long times = 1000000000;
        int o = 0;
        // keeps adding 1 to o for "times" times
        for (int i = 0; i < times; i++) {
            o++;
        }
        // prints the result of o
        System.out.println(o);
        // get the end time
        Timestamp end = new Timestamp(System.currentTimeMillis());
        // compare the 2 times and print it out in milliseconds
        System.out.println((end.getNanos() - begin.getNanos()) / 1000000);
    }
}

and this is an example of an unexpected result:

1000000000
-298

Process finished with exit code 0

EDIT:

The question has been marked as duplicate, where the answer indicates that System.currentTimeMillis() causes a +- 15ms difference, but this doesn't answer the fact that it becomes negative and the difference is larger than what was said. Further more, they say to use System.nanoTime() instead, but this also causes negative results, and only gives numbers in the hundreds like 300 or -200.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
behanep757
  • 87
  • 4
  • The terrible `java.sql.Timestamp` class was replaced years ago by the modern *java.time* classes defined in JSR 310. Furthermore, for benchmarking you should be using `System.nanoTime()` rather than date-time classes. – Basil Bourque Nov 29 '22 at 23:37
  • @BasilBourque both using `System.nanoTime()` standalone and subtracting the 2 values and `java.time.Instant` combined with `java.time.Duration` seem to be working correctly. However, the `System.nanoTime()` seems to be more consistent, and _java.time_ seemed to be more for comparing dates, so I don't know how accurate they are in the nano seconds. Which one should I be using (is more accurate)? – behanep757 Nov 29 '22 at 23:48
  • I deleted my Comment. I was having a brain spasm. Obviously subtracting a later and greater count of `System.nanoTime` from an earlier lesser one will always return a negative. My bad. – Basil Bourque Nov 29 '22 at 23:50
  • You can indeed use `Duration` class if you wish, though it adds no values for a small number of nanoseconds. The `Duration` class holds a count of whole seconds plus a count of nanoseconds for a fractional second. See [the source code](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/time/Duration.java). You should get same results from `endNano - startNano` as from `Duration.ofNanos( endNano - startNano ).toNanos()` – Basil Bourque Nov 29 '22 at 23:53
  • As @user16320675 says, the `getNano` method accesses the internally-stored fractional second kept as a count of nanoseconds. The existence of this `getNano` (& `getSeconds`) method is one of the few flaws in the design of the otherwise brilliant *java.time* classes. Both `getNano` & `getSeconds` methods unnecessarily reveal internal implementation details, breaking encapsulation. They really should be deprecated. Avoid the `getNano` method, and instead use only the `to…` methods: `toNanos()` for total length (if not exceeding the limit of a `long`) and `toNanosPart` for fractional second. – Basil Bourque Nov 29 '22 at 23:59
  • It's quite possible for `System.currentTimeMillis` to go backwards as it corrects for clock inaccuracy. – Louis Wasserman Nov 30 '22 at 00:08

0 Answers0