Yhirton Iowert
Yhirton Iowert

Reputation: 1

System nanoTime() has two trailing zeros

I have written some code using System.nanoTime() and the output did always have two trailing zeros. Now I wondered if that behavior is normal. I tried it on two laptops and it always stayed that inprecise, even though I remember having seen a particular precise value of System.nanoTime() somewhere in the past.

Here´s the code:

        long beginTime = System.nanoTime();

        for (int i = 0; i < 5; i++) {
            // doing something for time to pass
            long tpValue = 1;
            for (int j = 0; j < 14862; j++) {
                long value = 0x4b38e;
                value &= System.nanoTime();
                tpValue = (tpValue & value) | (tpValue ^ value);
            }
            long timePassed = System.nanoTime() - beginTime;
            System.out.println("Time passed: " + timePassed + " ns;" +
                    " Value calculated to pass time: " + tpValue);
        }

In this example on my device the value of tpValue would always be the same unless I divide System.nanoTime() by 1000.

Here the output:

 Time passed: 921000 ns; Value calculated to pass time: 308109
 Time passed: 9554500 ns; Value calculated to pass time: 308109
 Time passed: 10551800 ns; Value calculated to pass time: 308109
 Time passed: 11530700 ns; Value calculated to pass time: 308109
 Time passed: 12519400 ns; Value calculated to pass time: 308109

Upvotes: 0

Views: 74

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 340188

The Answer by HopefullyHelpful is correct and smart.

I can add my own pedestrian simple code showing counts of nanoseconds to the singles place.

for ( int i = 1 ; i <= 10 ; i ++ )
{
    System.out.println( System.nanoTime() ) ;
}

See this code run at Ideone.com.

15463866040482559
15463866041067009
15463866041111618
15463866041153989
15463866041196195
15463866041238231
15463866041279697
15463866041321311
15463866041362851
15463866041404462

And, by the way, to calculate elapsed nanos, I would use the handy Duration class.

long start = System.nanoTime() ;
…
Duration d = Duration.ofNanos( System.nanoTime() - start ) ; 
System.out.println( d ) ;  // Duration#toString generates text in standard ISO 8601 format. 
System.out.println( d.toNanos() ) ;

PT0.000843285S

843285

Upvotes: 2

HopefullyHelpful
HopefullyHelpful

Reputation: 1819

From https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--

This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().

Also your test has a few flaws, you're not polling nanotime very often. You basically have only 5 meaningful calls to long timePassed = System.nanoTime() - beginTime;

And you're not looking at System.nanoTime() directly, but at a difference of 2 System.nanoTime() values.

If you want to test resolution you can do any of the following

1.test your hypothesis that all values have a trailing 00 or same last 2 digits:

while(true) {
   long time = System.nanoTime();
   if(time % 100 != 0) {
       System.out.println(time)
   }
}

2.Or you can print the difference between a lot of call values, afterwards can filter all multiples of the smallest value with % and see if that is the actual resolution:

while(true) {
   long time = System.nanoTime();
   System.out.println(System.nanoTime()-time);
}

Upvotes: 4

Related Questions