-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
20
-
generic
-
os_x
A DESCRIPTION OF THE PROBLEM :
When calculating the elapsed time, the duration drifts between System.currentTimeMillis() and System.nanoTime() when the system is put to sleep. The millisecond time source for continues to accrue whereas the nano time source is paused. This does not appear to comply with a simple reading of the JavaDoc for what one might expect would be included within the the elapsed time.
"This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time."
This issue was discovered in [1] where the user did not appear have submitted this here as recommended. An expirable cache used nanoTime() to determine the remaining duration to not be impacted the wall clock was modified (e.g. by ntpd). This resulted in the application using a stale authentication token due to the excessive drift.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Read the current milli and nano time sources
2. Put the machine to sleep
3. Wake the machine up
4. Read the current time sources and compare the durations
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
0: Delta by millis=1 vs nanos=1
1: Delta by millis=2 vs nanos=2
2: Delta by millis=3 vs nanos=3
3: Delta by millis=4 vs nanos=4
...
99: Delta by millis=100 vs nanos=100
100: Delta by millis=101 vs nanos=101
101: Delta by millis=102 vs nanos=102
ACTUAL -
0: Delta by millis=1 vs nanos=1
1: Delta by millis=2 vs nanos=2
2: Delta by millis=3 vs nanos=3
3: Delta by millis=4 vs nanos=4
...
34: Delta by millis=35 vs nanos=35
... // sleep
35: Delta by millis=96 vs nanos=36
36: Delta by millis=97 vs nanos=37
37: Delta by millis=98 vs nanos=38
---------- BEGIN SOURCE ----------
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test;
public class NanoTimeTest {
@Test
public void test() throws InterruptedException {
long startMillis = System.currentTimeMillis();
long startNanos = System.nanoTime();
for (int i = 1; ; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.printf("%d: Delta by millis=%s vs nanos=%s%n", i,
Duration.ofMillis(System.currentTimeMillis() - startMillis).toSeconds(),
Duration.ofNanos(System.nanoTime() - startNanos).toSeconds());
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use System.currentTimeMillis() for elapsed time measurements.
FREQUENCY : always
When calculating the elapsed time, the duration drifts between System.currentTimeMillis() and System.nanoTime() when the system is put to sleep. The millisecond time source for continues to accrue whereas the nano time source is paused. This does not appear to comply with a simple reading of the JavaDoc for what one might expect would be included within the the elapsed time.
"This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time."
This issue was discovered in [1] where the user did not appear have submitted this here as recommended. An expirable cache used nanoTime() to determine the remaining duration to not be impacted the wall clock was modified (e.g. by ntpd). This resulted in the application using a stale authentication token due to the excessive drift.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Read the current milli and nano time sources
2. Put the machine to sleep
3. Wake the machine up
4. Read the current time sources and compare the durations
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
0: Delta by millis=1 vs nanos=1
1: Delta by millis=2 vs nanos=2
2: Delta by millis=3 vs nanos=3
3: Delta by millis=4 vs nanos=4
...
99: Delta by millis=100 vs nanos=100
100: Delta by millis=101 vs nanos=101
101: Delta by millis=102 vs nanos=102
ACTUAL -
0: Delta by millis=1 vs nanos=1
1: Delta by millis=2 vs nanos=2
2: Delta by millis=3 vs nanos=3
3: Delta by millis=4 vs nanos=4
...
34: Delta by millis=35 vs nanos=35
... // sleep
35: Delta by millis=96 vs nanos=36
36: Delta by millis=97 vs nanos=37
37: Delta by millis=98 vs nanos=38
---------- BEGIN SOURCE ----------
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test;
public class NanoTimeTest {
@Test
public void test() throws InterruptedException {
long startMillis = System.currentTimeMillis();
long startNanos = System.nanoTime();
for (int i = 1; ; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.printf("%d: Delta by millis=%s vs nanos=%s%n", i,
Duration.ofMillis(System.currentTimeMillis() - startMillis).toSeconds(),
Duration.ofNanos(System.nanoTime() - startNanos).toSeconds());
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use System.currentTimeMillis() for elapsed time measurements.
FREQUENCY : always