Timing is Everything Timing is Everything

by Chet Haase
02/15/2005

Contents
It's About Time
Going Beyond the Built-In Timers
Overview of the Timing Model
Features in TimingController
Introduction to the Code
Future Work
Appendix: Timing Resolution

Tick, Tick, Tick, Tick

Any time you introduce dynamic effects, animations, or time-based events to a Java application, you find yourself re-implementing the same functionality you have written for every application that required timing or animation. The built-in APIs are powerful, but they require that you write a fair amount of boilerplate code. This article considers the current situation and what is needed in a timing framework. The article refers to example code contained in a project posted on java.net: timingframework.dev.java.net.

There are so many different topics to discuss in this area, but for the purposes of this article, I will follow the introductory material with a look at these issues:

It's About Time

I recently wrote some simple demo applications to show off a particular point for a presentation on dynamic effects in Swing. In the course of this, I once again realized what a complete hassle it is dealing with timing and animation issues.

For example, suppose I wanted to have a simple animation where I move an image across the screen back and forth ten times, each time taking 500 milliseconds. I'd like to update its position every 30 milliseconds (about 30 frames per second), I'd like to pause for 50ms before starting, and finally, I'd like it to hold its final position when it is finished. I should be able to write code akin to the following:


        repeatCount = 10;         // do the animation 10 times
        duration = 500;           // each animation lasts 500 ms
        resolution = 30;          // update very 30 ms
        begin = 50;               // wait for 50 ms before starting
        repeatBehavior = Reverse; // reverse at the end of each animation
        endBehavior = Hold;       // hold final position
        Animation anim = new Animation(repeatCount, duration, resolution,
                                       begin, repeatBehavior, endBehavior); 

Unfortunately, here is the code I would have to write instead (using javax.swing.Timer):


	class MyActionListener extends ActionListener {
            public void actionPerformed(ActionEvent e) {
	        // Here's where all the logic goes: check the event time and
                // see whether to reverse or end the animation based on the
                // time elapsed
            }
	}
	
        resolution = 30;          // update every 30 ms
        begin = 50;               // wait for 50 ms before starting
        ActionListener myActionListener = new MyActionListener();
        Timer timer = new Timer(resolution, myActionListener);
        timer.setInitialDelay(begin);

This snippet doesn't look too bad until you realize that the real work is not yet done; implementing the insides of myActionListener can be pretty tedious.

Going Beyond the Built-In Timers

To be fair, the timing utilities in Java, java.util.Timer and javax.swing.Timer, are pretty powerful and can help you schedule time-based events. These classes let you create one-time and repeating events that will call into your application at scheduled intervals so that you can cause things to happen at those times.

This is a standard way to handle time-based events, such as animations; you are essentially telling the system "wake me up every n milliseconds." When you are woken up, you perform the appropriate action (change the appearance of an animating cursor, move an object on the screen, poll the network, send mail to your boss telling her how productive you are, whatever).

These are great utilities as far as they go, but I find that they don't go far enough. There is always other time-based functionality that I end up layering on top in order to deal with real application needs. For example, I usually want to run a timing event (such as the fading in of a component) for a set amount of time, but the Timer utilities assume one-time or indefinite operation and must be manually stopped when you are finished with them.

I thought it would be useful to codify some of the generic functionality that I tend to need into a higher-level utility that makes using timers a bit easier (at least for me). I've done this with the TimingController and associated classes in the java.net project TimingFramework. Ideally, this framework could be built upon to have more functionality that applications may need; perhaps that topic is ripe for another article or project some day in the future. But in the meantime, I hope that TimingController provides the following things for developers:

Overview of the Timing Model

The timing model can be pretty confusing, especially when you try to incorporate ideas of simple timing loops inside of larger frameworks, such as the animation example above, which runs for 500ms but is repeated ten times inside a larger animation structure. In an attempt to simplify this model, I use terms in this article and in the code that describe these concepts in a logical way: cycle and envelope.

"Cycle" is the term I use to describe the lowest level of timing; it is a timing event that runs for "duration" amount of time with "resolution" amounts of time in between each timing event, as depicted in this diagram:

Timing cycle

The diagram shows time progressing from left to right, along the arrow, with the beginning of the cycle at the far-left vertical line and the end of the cycle at the far right vertical line. Each tick shows a single timing event, which occurs with a frequency defined by the resolution.

The idea of duration is useful. Typically, in the demos I write, I want the animation to run for a specific amount of time and then stop. For example, if I want a component to fade in over the period of a second, I will want an animation to run that performs incremental fade-in capability (by changing the AlphaComposite used by the component's paint() method) and then I want that animation to stop one second after it starts. This framework allows you to specify that duration and the timer will stop automatically.

This definition of a cycle is fine for very low-level simple timing; we could build a utility that allows us to specify the duration and resolution, and we could have a timer that performs appropriately. This is basically just a simple layering of the duration concept over the current Java timers.

But we could also expand upon this idea by having the concept of a timing envelope, which I define to be a series of cycles. A simple diagram of an envelope follows:

Timing envelope

In this diagram, we once again see time marching forward from left to right, but now we are seeing how cycles and their envelope interact. Each envelope has the following:

Some important things about envelopes that are not called out in the diagram (because I found them difficult to draw; maybe if I had another dimension or two at my disposal in my drawing tool I could manage it) include:

Features in TimingController

TimingController depends on the underlying Timer capabilities of the existing libraries, but layers on other pieces of functionality that I have found useful in various applications. I'll highlight the main points of the framework here, but looking at the code itself is obviously the best way to understand how it all works. In particular, the SimpleAnimation example uses all of the different features of TimingController, so you can play with the features in the GUI and see how they were implemented in the code.

Overview

TimingController uses the concepts of Cycle and Envelope, as described above. Each TimingController is created with a Cycle and an Envelope, like this:


	TimingController myTimer = new MyTimerSubclass(cycle, envelope);

The Cycle object is created with:

The Envelope object is created with:

The TimingController object, after its start(), repeatedly calls into the TimingController.timingEvent() method with three values:

Note that, at this point, TimingController puts the real work of calculating values based on the timing events onto the application; the framework does not interpolate values for you. However, given the fraction of time that has elapsed in a cycle, it is usually straightforward for an application to calculate values based on each time event.

Note, also, that I use Cycle and Envelope in the code here to make it easy to translate between the text in this article and the code in the framework. In a real implementation of this framework, I might dispense with these extra classes entirely. They do a nice job of documenting the timing model structure, but in reality, they add a level of indirection that real users might not want to deal with constantly. But this more academic approach will do for now.

Timer Independence

There are various ways to use timers in your application, from the existing Timer classes to running a thread of your own and doing all of your own timer scheduling manually. I did not want to have any visible dependencies on a particular scheme to limit what someone could do with the framework. For example, the existing Timer classes have certain implications for timing resolution; if you ask for a timer to have a resolution of three milliseconds, but that timer uses a low-resolution timer, then you may not get anywhere near that resolution (see the section below on timing resolution for more information on this). So instead of having a visible and obvious dependency on one of these classes, this framework is independent of the existing utilities. It may depend on these utilities internally, but the behavior you get will not be constrained by these classes. In the timing resolution example, we could write the framework to have a fallback mechanism that works around the resolution constraints of any particular Timer mechanisms.

The framework has a mechanism for firing time events that is independent of existing Timer mechanisms. For example, the Swing Timer utility calls an ActionListener with a timing event, which is not the case with TimingController. When a timer event occurs in TimingController, it will call its own timingEvent() method; your application would subclass TimingController in order to receive this event.

Animation Fraction

A very simple way to write animations is to simply increment or decrement values by some amount every time a timing event occurs. For example, you might move an icon back and forth on the screen during some animation. Every time the Timer event occurs, you increment or decrement the x value of the icon position by one. This is fine for simple demos, but the approach breaks down quickly for anything complicated or where you need some dependable behavior.

For example, say you developed the application on some powerful system with gobs of memory and a fast CPU. You set up a Timer to call your application every five milliseconds, and your icon scoots across the screen at a rate of about 200 pixels per second. Then you run that demo on a system with little RAM, a slow CPU, and a very low-resolution timer. Now your application may only get called every 50 milliseconds, or may have very inconsistent performance and get called frequently sometimes and infrequently at other times. Now your icon staggers across the screen at a painful clip of 20 pixels per second, sometimes running much slower than that due to system hiccups.

Video games were written this way many years ago; they looked great on their target systems, but when they were run on systems much slower or faster than the target systems, the games were unplayable. I once saw an awesome graphics demo that spun around a wireframe piano model as it played a song; the graphics of the piano keys were perfectly synchronized with the sounds of the keys striking the strings. On the target system, it looked and sounded great; a very nice piece of work. But then I ran it again a few years later, when graphics performance was much greater and it looked ridiculous; the graphics finished rendering in about a tenth of the time as before, while the music still played at the same speed. This demo was written with the speed of the original system in mind. The movement of the piano model was not based on realtime values, but rather on the speed at which the runtime graphics system could draw the wireframe model.

The best way to handle animations so that they perform similarly across a wide variety of platforms is to base the animations on elapsed time instead of just the frequency of timing events. In the animating icon example above, this means you would base the position of the icon not on how many times your event was triggered, but on the total time elapsed for any given timing event. For example, if you wanted your icon to move at a constant rate of 200 pixels/second, then you would calculate the number of seconds elapsed in the animation from left to right and multiply that number by 200 to get the proper x value.

The existing Timer utilities send out events that are used simply to signal the recipient that a timing event has occurred. It is up to the client to choose what to do with that event. A typical thing to do in an animation would be to figure out how much time has elapsed in either the entire animation or since the last time an event fired and then to react accordingly.

I thought it would be more useful to send out the information the application actually needs here, instead of just a vanilla "timer fired" event (which is the way the current Timer classes work). Specifically, I wanted to be notified with the fraction of a given cycle that has elapsed. So if we are halfway through the duration of an animation, I would like to receive a notification that means "you are halfway through." Then I can easily use that fraction to calculate the correct value of my time-based animation.

TimingController helps out here by sending an event to timingEvent() with the fraction of completion of the current cycle. We can then use this fraction to calculate the appropriate value that we are trying to vary.

The fraction is useful in both the Repeat and Reverse behavior modes. In the simplest example, a fraction of .25 tells us that the animation is one-quarter of the way through. But suppose we are using a Reverse cycle and we are now running backwards; a value of .25 tells us that we are one-quarter of the way through the cycle, even if we got to that value by animating down from the end to the beginning of the cycle. That is, the fraction always represents the fraction between the beginning and end of a cycle, no matter whether we are running the timing sequence the first time, or in a Repeat cycle, or in a Reverse cycle.

Introduction to the Code

There should be little need for a full code walkthrough here; just check out the code, read the many comments, and play with the SimpleAnimation sample program to understand how it all works. But I will give some simple pointers to start you off.

The actual framework is in three classes in the timing package:

The other part of the sample code is SimpleAnimation, which is a simple GUI-based animation application used to test TimingController. The application allows you to specify the parameters for the Cycle and Envelope used in the application, and then start the animation running. Here's what you see when you start it:

Simple Animation

Most of the code in SimpleAnimation is used to set up and run the GUI. The core functionality that actually sets up and runs the animation is in the following lines in ControlPanel.actionPerformed():


	Cycle cycle = new Cycle(duration, resolution);
	Envelope envelope = new Envelope(repeatCount, begin, 
					 repeatBehavior, behavior);
	animation = new Animation(animationView, cycle, envelope);
	animation.start();

If you look at this code and then the first line of code at the beginning of this article, and you squint a bit, you can see that the approaches are pretty similar. Mere coincidence? I think not.

Future Work

My hope is that TimingController can become a building block in a larger framework of general animation utilities. There are many places to go from here, but there are a few key directions that seem worth calling out here:

I hope that we can eventually accomplish much of what I've outlined above. But it all starts with the basics, thus the TimingController utility and sample code.

Appendix: Timing Resolution

I could write a whole article (or more) on this topic alone, but I'll try to limit myself to the highlights here.

The issue here is that all platforms have different constraints on the resolution of their default timing systems. Resolution here means the amount of time between different time-based events. For example, the amount of time that a call to Thread.sleep() takes is dependent upon the resolution of some underlying timing system, as is a call to System.currentTimeMillis().

For most applications, this topic is irrelevant. If you are a static GUI application, then I don't even know why you have read this far; you don't have any need of time-based events. If you do have some simple animations or time-based events in your application, then chances are good that the resolution you require is of far coarser granularity than that provided by the default timers on most platforms, so you don't need to worry about timing resolution in general.

This section is not about those applications.

This section is for developers of performance-sensitive applications, including those with fast animations or where framerate is very important (games come to mind). Control freaks, that's what they are; developers that demand fine control over the scheduling of their animations and events.

These applications may care that when they ask to sleep for 10ms, they actually don't wake up for 16 milliseconds. Or when they ask a Timer to call them 500 times per second, they actually only get called 60 times per second.

The main problem is that the default timing systems on the native platforms are, in general, of low resolution, by which I mean that they do not have the granularity to deal with requests of two millisecond wakeups. For example, in native code on Windows, the usual way to find out how many milliseconds have elapsed is the Win32 function GetTickCount(). This is the native underlying utility used by System.currentTimeMillis() on that platform. GetTickCount(), however, has a default resolution of somewhere between 10 and 16 milliseconds, depending on the platform (for example, my Windows XP laptop has a default resolution of 16ms). If you call System.currentTimeMillis() on a platform with a resolution of 16ms, then you will only get answers in 16ms increments. So if you call it at one time, then call it one millisecond later, you will either get an answer that is the same as what you had before or a value that is 16ms greater (depending on whether you just crossed that 16ms boundary).

Similarly, Thread.sleep(long ms) is implemented using the native platform's sleep() function, which again might use a low-resolution timer by default. This may mean that when you ask to sleep for, say, 10ms, you will actually sleep for 16ms instead.

There is much more to write on this subject (especially as to workarounds, bugs filed, fixes, etc.), but the main reasons I wanted to call it out in this article include:

Note that the advice from the "Timing Fraction" section above applies well here; even if you are stuck with a timer with a lower resolution than you think you need, calculating your values based on elapsed times should give you what you need. Maybe you wanted your sprite to zip across the screen at 5000 times per second and you're only getting callbacks 60 times per second. It's unfortunate that it didn't match your ideal, but your icon will still look pretty smoothly animated at that lower rate, and it should look to the user as if it is moving at the same speed. It is just that the sprite's position will not be updated as often as you wanted.

Conclusions

I hope, foremost, that this article helps you to understand how timing works in Java in general. I also hope that you will download the code, play with it, understand it, and send in comments to help improve the framework. It would be wonderful to build on what we have and to create a more robust, functional, and general framework for assisting in all kinds of time-based applications.

Reminder: check out the code for this article at: timingframework.dev.java.net.

Chet Haase worked on the Java SE team at Sun for years, most recently as an architect in the Java Client Group.


 Feed java.net RSS Feeds