1

I've been searching for an answer to my dilemma and have found some useful tips but nothing that addresses my specific question, so I was hoping someone here might be able to help me out.

I'm trying to get a precise elapsed time to the millisecond in Java. I'm using System.nanoTime() to get the current time and implementing it in the following code. Mind you, this was code that I used to test it's precision.

long startTime = System.nanoTime()/1000000;
while (true)
{
System.out.println((System.nanoTime()/1000000)-startTime);
}

A portion of the output looks like this.

1110
1112
1112
1113
1114
1118
1120

The first digit is the number of seconds, the second, tenths of a second, the third, hundredths, and then the last is thousandths. You can't see it here, but I have precision to the hundredths place - no skipped or repeated numbers. The thousandths, though, is far from precise. 0 -> 2 -> 2 -> 3 -> 4 -> 8 -> 0. For what I'm doing, I need precision to the thousandths place and from all I have read it seems like System.nanoTime() should be able to provide precision to the millisecond.

Am I doing something wrong or is there another way I can get precision to the millisecond?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Antillies
  • 11
  • 2

3 Answers3

2

There are two factors here.

First, even System.nanoTime() is not necessarily really precise - it just uses the finest clock available (and does not follow clock changes, so it never goes backwards or jumps forward).

Second, your Java program is not the only program running on your computer - so your code (which essentially is the calling of the native nanoTime function and the output of the result) will take differently much time each time. For example, it may be that one output needs more than a full millisecond while another takes only a half or less.

Try to output some more digits (i.e. divide by a smaller number), the results will be helpful to understand.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
0

java.time

The old date-time classes are now supplanted by the java.time classes.

The java.time classes support a resolution up to nanoseconds. But remember that the actual resolution and accuracy depend upon the hardware clock of the host computer. So your results will vary.

Instant instant = Instant.now();  

2016-01-02T12:34:56.123456789Z

To reduce from possible nanosecond resolution to milliseconds, call the Instant::truncatedTo method.

Instant instantTruncated = Instant.now().trucatedTo( ChronoUnit.MILLIS );

2016-01-02T12:34:56.123Z

Keep in mind that most computer hardware clocks are not very accurate in the granularities of milliseconds-microsecond-nanoseconds.


Minor note: While the java.time classes support storing nanosecond resolution, in Java 8 the legacy implementation of Clock is limited to capturing the current moment with only milliseconds rather than nanoseconds. Java 9 brings a fresh implementation of Clock so the current moment can be captured in up to nanosecond resolution depending on the capability of your host computer clock hardware and host OS.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

Divide by 1 million after the subtraction, and use a long literal.

long startTime = System.nanoTime();

while (true)
{
    System.out.println((System.nanoTime() - startTime)/1000000L);
}

Demo (updated): http://ideone.com/X5RRa

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    That won't change the fact that the loop isn't guaranteed to execute at regular intervals, which seems to be what he's expecting. – Isaac Truett Mar 29 '11 at 17:14
  • I guess what I was anticipating is that the milliseconds would go up regularly (0, 1, 2, 3, etc). The tenths and hundredths do. You're saying this won't be the case for milliseconds? – Antillies Mar 29 '11 at 17:19
  • @Antillies: you expect the loop to run exactly once per millisecond? Why? – Matt Ball Mar 29 '11 at 17:21
  • @ Matt: I guess I was under the impression the loop would execute very quickly. But I guess I'm realizing by what you guys are saying that the time it takes the loop to execute is creating what I perceive as imprecision. Am I correct in understanding you that this isn’t imprecision but the loop not being able to print out the milliseconds as quickly as they occur because of the time the loop takes to execute? – Antillies Mar 29 '11 at 17:28
  • Thanks everyone for your help. I think I have a better idea of what I have to do now. – Antillies Mar 29 '11 at 18:06