High Resolution Timer in Windows

I wrote an OpenGL Display that scrolls spectrographic information supplied at very fast rates - from a 100 to a 1000 lines per second. The visual’s own display thread is slower than the pace at which the Data is supplied (typically 25 fps) so the idea is to scroll the information and then write a block (of the new information) and then sleep while accumulating information in a buffer until woken up again. All this is basically just to say that the Visual does a lot of work. The Display itself is only a small component in a much larger app I wrote that is used to analyze spectrogram data. The app has quite a few of these Displays all scrolling quite happily.

I wrote the Displays using GL4Java initially and when the App was pushed to the limit the machine was usually running at about 70% CPU usage. When I migrated to the JOGL apps I was happily suprised to find that the Processor usage decreased from 70% to about 50%.

Recently, however we have discovered a Time Acceleration problem in Windows whenever I use these displays. The PC Time literally “accelerates” and you can actually see the System Clock racing ahead. Sometimes the System Time would increase by almost 10 seconds in 1 minute. We also noticed that the Time problem became significant the faster we displayed information on the App. Of course, when working with information that is related to Time, having the System Time behave all willy-nilly is a serious complication for us.

Long story short, eventually I found the following bug report on Sun’s Bug Parade: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4500388. Which basically describes the bug as being a byproduct of switching between High Resolution and Low Resolution Time on Windows (Read the bug for a description of the problem). And it commonly occurs on Multithreaded apps with threads that sleep with a sub-ten-millisecond resolution.

Luckily there is a flag (-XX:+ForceTimeHighResolution) you can provide the VM so that it always uses High Resolution Time and never switches between the two. This solved the problem for us and I was very happy (phew). But here’s the clincher: I had feared that by using the flag we would suffer a performance impact, since the bug report warned that it might be so. I found however that the opposite was true in my case.

The CPU Usage was in fact, reduced by an incredible factor of about 5:1. With the flag enabled the app with GL4Java dropped from 70% to 30% CPU usage and with JOGL the CPU usage dropped from 50% to almost 0%. That’s right: 0%.

The engineers here couldn’t believe their eyes, that we were displaying information at a rate so fast its almost impossible to see and the CPU was idling around 0%, peaking to 4% every now and again.

Anyway this was really incredible for me as well and I was wondering if anybody else here have had a similar experience. And also if anybody is having problems with the System Time or High Processor usage; it might be worth it to check whether this flag makes a difference.

Thanks JOGL, you’ve definitely impressed me and my colleagues.

Glad things are working for you. It sounds like your app isn’t really CPU intensive, which is probably why avoiding system calls like timeBeginPeriod / timeEndPeriod (via -XX:+ForceTimeHighResolution) was beneficial. Our internal testing at Sun showed that (at least at one point) CPU intensive apps’ performance suffered by about 10% from the more frequent interrupts caused by having a higher time resolution. This is the reason why ForceTimeHighResolution isn’t on by default.

BTW, are you performing lots of Object.wait() calls in your application, or are they all coming from JOGL’s implementation? We necessarily use Object.wait/notify as a serialization mechanism in JOGL (typically through EventQueue.invokeAndWait) to perform all OpenGL work on one thread for better stability.

I have a few monitors that work on wait and notify, but all my display threads use sleeps.

And yes I have noticed that the JOGL is a lot more robust than GL4Java. Was able to run my app on several platforms without any modification to the code whatsoever. So the one thread mechanism does pay off. Only irritating thing I’ve noticed is that popups on Windows block the AWT Dispatch Thread so that my Visuals are blocked and do not scroll while the Popup waits for input. This doesn’t happen on X tho.

Does anyone know of a way to do this in code, rather than as a command-line parameter?

If you’re using Java 1.5 you don’t have to worry about this. In 1.5 you can use System.nanoTimer(), which will use the highest precision timer available.

There is a way to use “System.nanoTime()” in 1.4- as the code used to make this method is “hidden” in an existing package. Something along the lines of “sun.perf”- I’m not entirely sure, but searching around the Java2D forum for “high res timer” will be sure to get you the answer.

The issue here is not the measurement of time but they way that the Time Resolution Mode was being switched when doing thread sleeps and waits in a multithreaded environment in Java under Windows. Whenever time needs to be measured at a High Resolution the JVM will switch the Windows time resolution to high mode, do the time calculation, and then switch back to low resolution mode. The actual switching was the problem in my case, since my app was causing so many of them. By forcing the JVM to always use High Resolution mode in Windows the switching didn’t occur and thus the problem was solved.

If you want to measure time at a High Resolution you can simply use the QueryPerformanceCounters() WINApi call, or use Vlad Roubtsov’s JNI wrapper that uses that function.

Note that this is an issue that occurs only under Windows.

The class you want is sun.misc.Perf, but from what I’ve read on Sun’s site, it may be short-lived now that nanoTime() is in. I just bit the bullet, made my app require 1.5.x, and now have events scheduling with beautiful nanosecond precision.

If anybody’s interested, I built a very simple event scheduler using System.nanoTime(). Here’s the code.

First, the Scheduler. This class simply maintains a list of Events (in priority order) and calls them if their timer says they’re ready. All the outside world needs to do is call Scheduler’s update() once per frame to check if any timers are ready to fire.

The design decision was made not to make this a singleton by going all-static, in case we wanted a separate scheduler for specific characters or modules.



/**
 * This class (which we will use as a singleton-like object) will fire events on cue using a high-performance timer.
 * @author  Jaeden
 */
public class Scheduler
{
    /** List of events to maintain */
    private java.util.ArrayList listEvents = new java.util.ArrayList();
    
    /** If 'true', the list has been added to and needs a sort() */
    private boolean bNeedsSort = false;
    
    /** Creates a new instance of Scheduler */
    public Scheduler() {}
    
    /** Add an ScheduledEvent to the scheduler 
     *  @param evt Event to add */
    public void addEvent(ScheduledEvent evt) 
    {
        listEvents.add(evt);
        bNeedsSort = true;
    }
    
    /** Sort the events by priority */
    public void sort()
    {
        bNeedsSort = false;
        Object[] array = listEvents.toArray();
        listEvents.clear();
        java.util.Arrays.sort(array, new ScheduledEvent.EventComparator());
        for (int i = 0; i < array.length; i++)
            listEvents.add(array[i]);
    }
    
    /** Check the Events, firing those that should be fired */
    public void update()
    {
        // sort if we need it
        if (bNeedsSort) sort();
        
        // run all our events if it's time
        for (int i = 0; i < listEvents.size(); i++)
        {
            ScheduledEvent e = (ScheduledEvent)listEvents.get(i);
            if (e.isReadyToRun())
                e.run();
            if (e.destroyOnRun())
                listEvents.remove(i);
        }
    }        
}

I then present a scheduled event, for one-time events that will be auto-deleted by the Scheduler after they are run.


public class ScheduledEvent
{
    /** If 'true', we should destroy the event once it is run */
    private boolean bDestroyOnRun = true;
    
    /** The time at which to run the event */
    private long lTimeToFire;
      
    /** The Runnable to track */
    private Runnable runnable; 
    
    /** Priority (this is how events are sorted for calling order in the scheduler */
    private int iPriority;
    
    /** Check if we should destroy this object when it is run 
        @return bDestroyOnRun */
    public boolean destroyOnRun() { return bDestroyOnRun; }
    
    /** Set whether we should destroy this object when it is run
     *  @param bDestroy 'true' if it should be destroyed */
    public void setDestroyOnRun(boolean bDestroy) { this.bDestroyOnRun = bDestroy; }    
    
    /** Accessor for priority
     *  @return iPriority */
    public int getPriority() { return iPriority; }
    
    /** Mutator for priority
     *  @param iPriority priority */
    public void setPriority (int iPriority) { this.iPriority = iPriority; }
    
      /** Accessor for runnable object
     *  @return runnable */
    public Runnable getRunnable() { return runnable; }
        
    /** Accessor for time to fire
     *  @return lTimeToFire */
    public long getTime() { return lTimeToFire; }

    /** Checks if it is time to fire the event
     *  @return 'true' if it's action time! */
    public boolean isReadyToRun() 
    {
        return (lTimeToFire <= System.nanoTime());
    }
    
    /** Static method to retrieve the number of nanoseconds for an interval given the number of 
     *desired frames per second 
     *  @param iFPS desired FPS
     *  @return nanosecond interval between frames */
    public static long getNanoInterval(int iFPS) 
    {
        return (long) ( NANOSEC_IN_SEC * ( 1.0f / iFPS ) );
    }
    
     /** Number of nanosec in a sec */
        public static final int NANOSEC_IN_SEC = 1000000000; 
        
    /** Run the timed object if it's time */
    public void run()
    {
        runnable.run();               
    }
    
    /** Set the time to fire an event
     *  @param lTime time to fire (as nanoseconds FROM NOW) */
    public void setTime(long lTime)
    {
        lTimeToFire = System.nanoTime() + lTime;
    }
    
    /** Creates a new instance of ScheduledEvent 
        @param r Runnable object to schedule 
        @param lWhen The time, in NANOseconds, FROM NOW, at which to fire the event 
        @param iPriority priority in the call order */
    public ScheduledEvent(Runnable r, long lWhen, int iPriority) 
    {
        this.runnable = r;
        lTimeToFire = System.nanoTime() + lWhen;
        this.iPriority = iPriority;
    }
    
    /** Class for comparing events */
    public static class EventComparator implements java.util.Comparator
    {        
        /** See which has the higher priority
         *  @param obj an event
         *  @param obj1 another event 
         *  @return -1 if obj is lower, 1 if obj1 is lower, 0 if they are equal */
        public int compare(Object obj, Object obj1) 
        {            
            int i0 = ((ScheduledEvent)obj).getPriority();
            int i1 = ((ScheduledEvent)obj1).getPriority();
            
            if (i0 > i1) return -1;
            if (i1 > i0) return 1;
            return 0;            
        }        
    }
}

And finally, a subclass of ScheduledEvents for events that should happen continuously, like rendering.


/**
 * Used for scheduled events that will be constantly happening, like rendering and AI updates.
 * @author  Jaeden
 */
public class RecurringEvent extends ScheduledEvent 
{
    
    /** Time interval */
    private long lInterval;
    
    /** Accessor for the time interval
     *  @return lInterval */
    public long getInterval() { return lInterval; }
    
    /** Mutator for time interval 
     *  @param lInterval new interval */
    public void setInterval(long lInterval) { this.lInterval = lInterval; }
    
    /** Creates a new instance of RecurringEvent
         @param r Runnable object to run 
         @param lTime time in NANOSECONDS between runs  
         @param iPriority priority in the call order */
    public RecurringEvent(Runnable r, long lTime, int iPriority) 
    {
        super(r, lTime, iPriority);
        lInterval = lTime;
        setDestroyOnRun(false);
    }
    
    /** Runs the event. 
     *  Also will set the time to the next appropriate time. */
    public void run()
    {       
        // reset the timer.
        setTime(lInterval);
        super.run();        
    }
}

Hope it’s useful to you guys.

I’m glad to see there are still Java programmers out there who use the correct braces convention. ;D

prepares for sudden onslaught of meaningless flames

One more for that point (totally off topic but so enjoying)