tags:

views:

475

answers:

7

Is tight looping in a program bad?

I have an application that has two threads for a game-physics simulator. An updateGame thread and a render thread. The render thread is throttled by causing the thread to sleep for some milliseconds (to achieve the frame-rate I want) and the updateGame thread (that updates my in game objects positions based off some physics equations) was previously throttled by a 10 millisecond sleep.

However, I recently unthrottled the updateGame thread and the simulation of my objects movement seems to be significantly more realistic now that I have taken out that 10ms sleep. Is it bad to hot loop or have a tight loop?

private class UpdateTask implements Runnable
{
    private long previousTime = System.currentTimeMillis();
    private long currentTime = previousTime;
    private long elapsedTime;


    public void run()
    {
        while(true)
        {
     currentTime = System.currentTimeMillis();
     elapsedTime = (currentTime - previousTime); // elapsed time in seconds


     updateGame(elapsedTime / 1000f);

      try {
       Thread.currentThread().sleep(1);
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }

     previousTime = currentTime;
     }
    }
}

In this example I'm just sleeping for 1ms (and from my understanding with how millisecond accuracy and the sleep function works this is probably more like 5-10ms. If I sleep for any more than this it starts to have impacts on the accuracy of my collision detection and physics model.

Is it a bad practice to have tight loops or loops with 1ms sleeps in them? Is there something else I should do instead?

+2  A: 

It's only "bad" if it has an adverse impact on something else in your system. Rather than sleeping for 1ms, you might block on a condition that warrants updating, with a minimum of 1ms. That way you'll always sleep for at least 1ms, and longer if there's nothing to do.

Adam Liss
+1  A: 

As Adam has pointed out in his answer, there may be an adverse impact on the performance of the system.

I've also tried making games in a very similar manner (having a rendering and motion calculations on separate threads) and I have found that not having the Thread.sleep will cause the Java application to take a very significant portion of the CPU time.

Another thing to consider is that the system timer itself. As you've mentioned, although the Thread.sleep method is takes in the number of milliseconds to sleep, but that precision is dependent (as noted in the API specifications) on the timer provided by the operating system. In the case of Windows NT-based operating systems, the timer resolution is 10 milliseconds. (See also: System.currentTimeMillis vs System.nanoTime)

Yes, it is true that having the Thread.sleep has the potential to decrease the performance of your application, but not having that can cause the system utilization by the application to skyrocket.

I would guess the decision comes down to whether the application should take up a significant portion of the system utilization, or to act nice and share the CPU time with the other applications running on the system.

coobird
+8  A: 

I read a really great post about efficiently and effectively executing physics calculations loop: Fix Your Timestep!

When a game is running that is usually the main application that the user cares about so tight looping is not that big of a deal. What you really should do though schedule your updates. You should know how long -- at your target framerate -- that your frame has to execute. You should measure the time that your frame took and only sleep for the time that your frame took minus that known frame time. That way your system will lock into a frame rate and not vary with the amount of time that your frame takes to render.

Another thing is that I don't believe that Thread.sleep has a very good resolution, well over 5 milliseconds, you may want to look for a more accurate timer available for Java.

joshperry
I have two threads, my updateGame thread and my rendering thread. My rendering thread is locked to a maxFrameRate as you say based off it's elapsed time.
Simucal
@joshperry, reading the article now
Simucal
Big upvote for 'fix your timestep'. Back in the Dark Ages we used similar techniques for justifying text!
Norman Ramsey
A: 

For a game, probably not. Just make sure your game pauses when the switches tasks.

jmucchiello
A: 

You would actually want to use Thread.yield() in this case. It is possible that one thread will run continuously, and not allow any other threads time to execute. Placing a yield call at the end of each iteration gives the scheduler a hint that it is time to allow other threads to run as well.

madlep
A: 

Also consider laptop users, running a tight loop continuously will keep the CPU running hard, and this will chew through their battery (many flash games are guilty of this). Something to consider when deciding whether to throttle your loops or not.

RodeoClown
+1  A: 

The answer by joshperry is pretty much what you want, but there are also a few ways about it. If you are using multiple threads, you have to also deal with locking etc. Depending on your game architecture that may / may not be a big deal. For example, do you do lots of locking, is there a lot of message passing between threads etc. If you are a traditional game you usually have a single main loop - I have a queue of CMD objects (runnable if you like, but can also be more event bus like in nature) that are executed continuously until the queue is empty. The thread then waits until it is signaled that a new cmd is in the queue. For most games this is usually enough. So the question then becomes how / when are cmds added. I use a timer/scheduler (also note the comments about java time resolution) to add a cmd to the main loop at the required frame rate. This has the advantage of also being kind to laptops etc. On startup you can also then benchmark the system to see how fast it is running, and then set an appropriate frame rate (ie. start with a supported base, then work to a max). Benchmarking or using user specified performance hints (ie. amount of rendering detail) can then be used by each type of cmd (ie. the render scence cmd / event looks at the performance settings for detail etc). (note - cmds dont' have to be runnable, they can be more like an event bus with listeners that are invoked on the main thread).

Also if a task wants to then use multi-thread/core's the handler for the cmd (if its an event type model - i personally like the event model - its easier to access the shared state info without needing global singletons) can then spawn multiple tasks (say using an existing thread pool - so the cost of new threads are not hit every cmd) and then use a barrier type class to wait for all the tasks to complete. This method usually makes locking easier, as each cmd (or system) usually has different locking requirements. Thus you can implement just the locking for that system and not have to worry about locking between sub systems - ie. for physics you can lock on bundles of objects in the game area, and each forked thread in the thread pool then worries only about its objects ie. thread1 handles objects1 to 20, thread2 objects 21-40 etc (this is just to illustrate the concept of how each cmd can implement a custom locking algorithm that works best for what it is doing, without having to worry about what other sub systems are doing with shared state data).

The important thing is to look at how and why you are using threads and locking etc.

nso1