JDK-6464007 : System clock acceleration still exists on Windows XP
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 5.0u6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-08-25
  • Updated: 2011-02-16
  • Resolved: 2006-08-28
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
ver XP SP2

EXTRA RELEVANT SYSTEM CONFIGURATION :
Netbeans 5.0 DELL Inspiron 9300 Centrino 2.1GHz 1 GB RAM

A DESCRIPTION OF THE PROBLEM :
  Bug exists but has been closed: http://developer.java.sun.com/developer/bugParade/bugs/4814012.html

This problem still exists. We are running a multithreaded application that is CPU intensive and find that the system clock runs out by a few minutes each hour. Network time controllers reset the System Clock and the app is unresponsive until the clock catches up to the previous time. Threads spin inside the Thread.sleep state and timers do not fire. The app is heavily time dependent and the unresponsive state is unacceptable from a customer and performace perspective.

The example in the bug listed above show clock increases of about 15ms per minute. It only occurs if both worker threads are running in the example from the buglist. It still occurs if the threads sleep for more than 10ms. Appears to stop if the sleep interval is increased to 20ms, but could appear in longer test runs (untried).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the example listed in http://developer.java.sun.com/developer/bugParade/bugs/4814012.html

Also happens when main thread time is reduce to 60 seconds not 10 minutes.

Appears to be an issue when CPU is under heavy load >50%.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected the reported time taken to match the Thread.sleep interval on the main thread.
ACTUAL -
Worker thread sleep time, Main thread return time, Expected return time, Delta

1ms, 60047, 60000, 47ms
10ms, 60016,60000,16ms
15ms,60015,60000,15ms (all high CPU usage >50%)
20ms,60000,60000,0ms (low CPU usage <10%)
25ms,60000,60000,0ms
30ms,60000,60000,0ms



ERROR MESSAGES/STACK TRACES THAT OCCUR :
No crash.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * SleepTest.java
 *
 * Created on 22 August 2006, 11:22
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

/**
 *
 * @author chornby
 */
public class SleepTest {
    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
                System.out.println("Starting " + Thread.currentThread().getName());
                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(60000);
                } 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
        SleepTest tb = new SleepTest();
        
        // 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, 5);
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None found. One would be most welcome! AFAIK the suggested workaround -XX:+ForceTimeHighResolution does not work on JRE 5?

Comments
EVALUATION Bug 4814012 was closed as a duplicate of 4500388. Bug 4500388 was in turn "addressed" by adding the ForceTimeHighResolution flag to avoid continual switching of the timer resolution. Unfortunately the fix for 4500388 was implemented incorrectly - though this went unnoticed for a very long time - and that issue is being tracked as bug 6435126. That incorrect fix actually disabled all use of the high resolution timer if ForceTimeHighResolution was specified. The problem of system clock acceleration on Windows is a known problem with the way in which high resolution timers are used. This ongoing problem is being tracked as CR 5005837, which is tracking all windows timers issues. Consequently this bug report has to be closed as a duplicate of one of the above. Please note that there is a simple work-around for the ForceTimeHighResolution flag not working - as described in 6435126 and repeated below. Hopefully this will alleviate the problem you are seeing. Also note that the problematic use of the high resolution timer only occurs for sleep times that are not a multiple of 10ms. But note that requesting a sleep time of 10ms when the system timer has a resolution of 10ms could easily result in sleep between 0 and 20ms without even considering scheduling issues. You cannot expect such sleep times to be accurate. Further, you cannot use System.currentTimeMillis() to accurately measure such times as it too has a normal resolution of 10ms. Using System.nanoTime will (on most systems) provide much better resolution, but it too has issues on the Windows platform due to the way Windows implements the high resolution clock. I am confused about the degree of the problem. Earlier reports have mentioned 1 minute per hour; this report says several minutes per hour, but also says 15ms per minute which is less than a second per hour. If you can clarify this please add SDN comments to one of the open bugs: 6435126 or 5005837. Thanks.
28-08-2006

WORK AROUND Do not use ForceTimeHighResolution but instead, at the start of the application create and start a daemon Thread that simply sleeps for a very long time (that isn't a multiple of 10ms) as this will set the timer period to be 1ms for the duration of that sleep - which in this case is the lifetime of the VM: new Thread() { { this.setDaemon(true); this.start(); } public void run() { while(true) { try { Thread.sleep(Integer.MAX_VALUE); } catch(InterruptedException ex) { } } } }; Note that as the sleep never terminates the timer period is never restored by the VM. This is not a problem however because it seems windows tracks the changes to the timer in the process control block and removes the change when the process terminates. This particular feature of these API's is not documented however, but the use of the PCB is mentioned in one of the "inside NT" articles, because it stops a process from calling timeEndPeriod if it never called timeBeginPeriod. It does make sense that the OS would not simply trust the application to do the right thing here.
28-08-2006