Thread.sleep(1) is a brutal way to implement sync

Started by sindri, August 07, 2008, 01:29:09

Previous topic - Next topic

sindri

try this


public class Test
{
   public static void main(String[] args) throws Exception
   {
      long one_second = 1000000000;
      long fps = 75;      
      long interval = one_second/fps;
      
      long nstart;
      long nend;
   
      while (true)
      {
         nstart = System.nanoTime();
         
         doWork();
         
         nend = System.nanoTime();
         
         // this helps to regulate the time between iterations by
         // consuming any spare nanoseconds between the time it
         // took to do the work and the target frames per second
      
         if (nend-nstart < interval)
         {
            while (nend-nstart < interval)
            {
               nend = System.nanoTime();
            }
         }
         else
         {
            System.err.println("It is taking longer to doWork than is allowed if you want to hit " + fps + " fps.");
         }
      }
   }
   
   private static void doWork() throws Exception
   {
      Thread.sleep(9);
      System.err.println(System.currentTimeMillis());
   }
}

kappa

Yes you are correct this method is nicer, however lwjgl's minimum requirements are Java 1.4 and System.nanoTime() is a Java 1.5 function.

oNyx

More and more machines are laptops. Using 100% CPU where 5% would have been sufficient isn't a good idea.

Besides... your algorithm only caps the minimum frame time (it's pretty much the simplest solution for this problem). That causes more dropped frames than slightly improved algorithms such as lwjgl's sync, which considers the overtime of the previous frame (without adding it all up).

Additionally, nanoTime isn't very robust. It's a very fragile timer. I wouldn't use it for anything except for benchmarks which only need to work on a single machine.

Believe it or not, but I spend a few hours with this very topic (I wrote the sync code) and the current implementation is most likely as good as a general capping method can get.

sindri

aight, I will go green on the cpu, but no Thread.sleep in the tight loop.

Thanks!

                // this helps to regulate the time between iterations by
                // consuming any spare nanoseconds between the time it
                // took to do the work and the time it should take to
                // hit the target frames per second

                if ((nend-nstart) < interval)
                {
                    long wait = interval-(nend-nstart);
                    long millis = wait/1000000;
                    long nanos = wait%1000000;

                    Thread.sleep((int)millis, (int)nanos);

                    while ((nend-nstart) < interval)
                    {
                        nend = System.nanoTime();
                    }
                }
                else
                {
                    System.err.println("It is taking longer to doWork than is allowed if you want to hit " + fps +
                                       " fps.");
                }