United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4500388 : Calling Thread.sleep with small argument affects system clock on windows

Details
Type:
Bug
Submit Date:
2001-09-06
Status:
Closed
Updated Date:
2012-10-08
Project Name:
JDK
Resolved Date:
2002-04-04
Component:
hotspot
OS:
windows_nt,windows_xp,windows_2000
Sub-Component:
runtime
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.3.0,1.3.1,1.3.1_04,1.4.0,1.4.1,5.0u4
Fixed Versions:
1.3.1_04 (04)

Related Reports
Backport:
Backport:
Duplicate:
Duplicate:
Relates:
Relates:
Relates:
Relates:

Sub Tasks

Description
Multithreading timers less than 10 ms causes Windows clock to run too fast.Compile the test case on JDK 1.3.0 and run on Windows 2000 Professional,Use an independent timer (like a kitchen timer) to measure the execution time of the program.

The 5 ms sleep causes a call to NTSetTimerResolution in the OS to set the timer to 1 ms resolution (in order to discriminate the passage of 5 ms).
 The multithreading of the timers is causing a problem.
 
 The problem is not observed in classic mode, or using the MS virtual machine.

 TESTCASEBEGIN
 /**
  * This class is meant to demonstrate an issue with the system time when 
running the HotSpot VM and sleeping for less than 10 ms. When it is run with the HotSpot VM, the system time will be off. The program will run for 10 system minutes, but when verifying with a stop watch, is took only 9 minutes and 50 seconds.
  * Steps to try this:
  * 1. Set a count-down timer to 10 minutes.
  * 2. At the same moment, run the application and start the count-down timer.
  * 3. At the moment the software stops, stop the timer. When the timer is 
       zero,it means that the system took 10 real minutes. When there is time           left on the timer, the system took less than 10 minutes.
+  * Another way to try this:
+  * 1. Remove the code where the "timer" is created so the application
+  *    will not stop after 10 minutes.
+  * 2. Set an external clock at exactly the same time as the computer clock.
+  * 3. Run the application.
+  * 4. After a couple of hours, compare the system clock with the external 
        clock.
+ Note that the system clock is a couple of minutes fast.
   */


 public class TestBase {
    public int launchThread(final int id, final int sleepTime) {
 
       // Create a new thread object
       Thread t = new Thread(new Runnable() {
                                public void run() {
                                   // Loop forever
                                   while (true) {
                                      // Print the ID
                                      System.out.print(""+id);
                                      // Do some processing
                                      for (int i=0; i<1000; i++) {
                                         for (int j=0; j<1000; j++) {
                            double x = (double)i * j / j + i - j * j;
                                        }
                                      }
               // Sleep for the amount specified in the sleep time
                                     
   try {
	Thread.currentThread().sleep(sleepTime);
                 }
                    catch (InterruptedException e) {
                                         ;
                                      }
                                   }
                                }
                             });
       // Start the thread
       t.start();
       return 0;
    }
 
    public static void main(String[] args) {
       // Create a Thread that will print the ms time every 30 seconds
       Thread timer = new Thread(new Runnable() {
                                    public void run() {
                                       // Print the begin time
                                       long start = System.currentTimeMillis();
                      System.out.println("Start time: " + start);
                                       try {
                                          // Sleep for 10 minutes
                                          Thread.currentThread().sleep(600000);
                                       }
                                       catch (InterruptedException e) {
                                          ;
                                       }
                                       // Print the current time
                  System.out.println("time: " +(System.currentTimeMillis() - start));
                                       System.exit(0);
                                    }
                                 });
       // Start the timer thread
       // Remove this line of code when it is not desired to stop the app after 10 minutes.
       timer.start();
 
       // Create a new test base object
       TestBase tb = new TestBase();
 
       // Launch a thread with a 5 ms sleep time
       tb.launchThread(1, 5);
 
       // Launch a thread with a 10 ms sleep time
       tb.launchThread(2, 10);
    }
 }
 
 
 
 
 
 TESTCASEEND

                                    

Comments
EVALUATION

Hotspot uses Windows routines timeBeginPeriod() and timeEndPeriod() to change the Windows timing resolution from its default value to one millisecond and back during a Thread.sleep(). Frequently changing the resolution appears to be causing errors in Windows time keeping (speculation).  Simply avoiding timeBeginPeriod use would cause errors in timing short delays less than 10ms. 

Here's similar analysis and a suggested solution from Ken Russell:

"I don't recommend removing the timeBeginPeriod()/timeEndPeriod() calls
because that will prevent sleeps from under 10 ms from working properly. If
this is a critical customer issue then one solution would be to provide a
product-mode flag which would disable the effect of the
HighResolutionInterval class and also set the time interval to 1 ms when the
VM starts up, incurring a performance penalty but maintaining correctness. I
assume the skew is caused by the multiple calls to
timeBeginPeriod()/timeEndPeriod() and not simply by the increasing of the
resolution of the timer." (from 8/18/2001 email).

###@###.### 2001-09-18

I ran the test case on an NT 4.0/SP4 system and it ran in 10 minutes two seconds. On a W98/SE system it ran in 10 minutes one second.

###@###.### 2001-09-18
                                     
2001-09-18
WORK AROUND

None
                                     
2004-06-11
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.3.1_04
1.4.0_02
hopper

FIXED IN:
1.3.1_04
1.4.0_02
hopper

INTEGRATED IN:
1.3.1_04
1.4.0_02
hopper


                                     
2004-06-14



Hardware and Software, Engineered to Work Together