LWJGL Forum

Programming => General Java Game Development => Topic started by: bobjob on October 03, 2010, 12:32:02

Title: Timer Comparison
Post by: bobjob on October 03, 2010, 12:32:02
Iv started a benchmark demo package for LWJGL. I noticed the sync() julted on my machine a bit.
So i implemented a timer for nanoTime() and currentMill...
and found that nanoTime() was actually the smoothest of the lot.


machine
Quote
OS Name   Microsoft Windows 7 Professional
Version   6.1.7600 Build 7600
System Manufacturer   Gigabyte Technology Co., Ltd.
System Model   G31M-ES2L
System Type   X86-based PC
Processor   Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz, 2500 Mhz, 2 Core(s), 2 Logical Processor(s)

Has anyone else found this with Windows 7?

Currently the benchmark just loads a crysis nano suit, and spins it.
Can someone else with windows 7 run it, and test each timer on the menu to check which timer runs the smoothest.
You will need to use your eyes to discern which method is smoothest.


also in regards to to the benchmark applet. I was wondering if anyone would like to contribute some 3D demos to it.
It would be cool if anyone has implemented some cool effects that hog up system resources.

So if anyone is interested in it, Ill post the process to add a Benchmark test.

edit:
almost forgot about the url:
have2chat.net/benchmark (http://have2chat.net/benchmark)
Title: Re: Timer Comparison
Post by: bobjob on October 03, 2010, 12:58:33
In regards to the Timer, in the applet a variation of sync() is called, that doesnt syncronize with "Global.lock" as it was required in order to have an uncapped frame rate for a benchmark test.
None the less, the lag jults were present before moving the sync() process out of the LWJGL Thread.
Title: Re: Timer Comparison
Post by: princec on October 03, 2010, 17:13:27
The display.sync method isn't all that great. I don't use it.

Cas :)
Title: Re: Timer Comparison
Post by: bobjob on October 03, 2010, 18:24:30
The display.sync method isn't all that great. I don't use it.

Cas :)
Good to know, I thought only few would have problems with it.
Title: Re: Timer Comparison
Post by: basil on October 03, 2010, 18:38:08
Timer + Java = Pain in the arse.

yesterday I checked out the gagetimer. works very good for windows XP, on vista/7 similar to nanoTime(). check out http://www.cokeandcode.com/info/tut2d-2.html for details.
Title: Re: Timer Comparison
Post by: Matzon on October 03, 2010, 19:37:13
if the sync method is broken, then please propose a solution...

and please see http://lwjgl.org/forum/index.php/topic,3398.msg18881.html#msg18881 and followups
Title: Re: Timer Comparison
Post by: bobjob on October 03, 2010, 19:56:05
if the sync method is broken, then please propose a solution...
I didnt think it was broken, thought maybe it was just my machine.

Timer + Java = Pain in the arse.

yesterday I checked out the gagetimer. works very good for windows XP, on vista/7 similar to nanoTime(). check out http://www.cokeandcode.com/info/tut2d-2.html for details.
GAGE timer is public domain, so I dont see a problem with using it. Got it working on Windows 7 32 bit, It only has the one dll, so Im asuming it wont work with 64bit (cant test it as I dont have 64bit installed).
the dll compresses to 35k.

source of the dll is extremely small, can anyone compile a 64bit version?

*attached native first version.
Title: Re: Timer Comparison
Post by: bobjob on October 03, 2010, 20:25:13
a few notes about the source code for GAGE.
* cant find the correct version of Java, it uses java.vm.version, instead of java.version to find >= version 5 (so nano timer doesnt work for 1.6+)
* will use the nano timer before it will use the native timer
* uses yeild() when using sleepUntil()

all of these things are changed in the timer.zip attached to the previous post.
also there is a class SyncTimer(), that works just like the LWJGL Timer (except its not syncronized to the LWJGL thread)

This doesnt really seem like a good solution, as it still requires mostly Java.
Title: Re: Timer Comparison
Post by: basil on October 03, 2010, 22:51:57
well, the gage-thingy is good but then maybe a bit too much.

I use only the
Code: [Select]
com.dnsalias.java.timer.windows.WindowsTimer class and do a
Code: [Select]
System.loadLibrary ( "timer" ); by myself.

So I end up only with the two methods that make a difference : getResolution () and getClockTicks ()

fetching mills : return (t.getClockTicks () * 1e3 ) / t.getResolution ();
fetching nanos : return (t.getClockTicks () * 1e9 ) / t.getResolution ();
(where t = new WindowsTimer ();)

works very similar to :

return System.nanoTime () * 1e6
return System.nanoTime ()

I think its better to figure the OS and java-version by myself.

about the jwlgl sync method, its not broken. java timer on windows is broken ;)

another interesting article : http://andy-malakov.blogspot.com/2010/06/alternative-to-threadsleep.html

but remember, Thread.sleep(0) or Thread.yield() = 100% cpu usage.
Title: Re: Timer Comparison
Post by: Matzon on October 04, 2010, 04:42:44
well, afaik, nanotime is still broken on windows  except on windows 7+ ?
Title: Re: Timer Comparison
Post by: princec on October 04, 2010, 11:06:48
I'm not sure my method is universally acceptable yet. I'll post it up in a bit and see what you think.

Cas :)
Title: Re: Timer Comparison
Post by: basil on October 04, 2010, 12:50:37
well, afaik, nanotime is still broken on windows  except on windows 7+ ?
not sure what you mean but if its about the "timer goes backwards" problem, ... no, its not working on win7.

usual fix looks like this :
Code: [Select]
  public void start ()
  {
    while ( start < last )
      start = System.nanoTime ();

    last = start;
  }
now, at least it "looks" fixed.
Title: Re: Timer Comparison
Post by: princec on October 04, 2010, 16:09:20
Ok, now don't laugh, but this is our current main game loop. It doesn't use Display.sync() at all, and relies solely on the LWJGL timer.
Code: [Select]
private void run() {
int ticksToDo = 1;
long then = Sys.getTime() & 0x7FFFFFFFFFFFFFFFL;
long framesTicked = 0;
long timerResolution = Sys.getTimerResolution();

while (!finished) {

if (Display.isCloseRequested()) {
// Check for O/S close requests
exit();

} else if (Display.isActive()) {
// The window is in the foreground, so we should play the game
long now = Sys.getTime() & 0x7FFFFFFFFFFFFFFFL;
long currentTimerResolution = Sys.getTimerResolution();

if (currentTimerResolution != timerResolution) {
// Timer resolution change -- all bets off
timerResolution = currentTimerResolution;
then = now;
}

Resources.manage();

if (now > then) {
long ticksElapsed = now - then;
double shouldHaveTickedThisMany = (double) (getFrameRate() * ticksElapsed) / (double) timerResolution;
ticksToDo = (int) Math.max(0.0, shouldHaveTickedThisMany - framesTicked);
if (ticksToDo > 5) {
// We're overrunning!
ticksToDo = 1;
then = now;
framesTicked = 0;
counter = 0;
}
} else if (now < then) {
ticksToDo = 0;
then = now;
framesTicked = 0;
counter = 0;
} else {
ticksToDo = 0;
}

if (ticksToDo > 0) {
for (int i = 0; i < ticksToDo; i ++) {
if (i > 0) {
Display.processMessages();
catchUp = true;
} else {
catchUp = false;
}
tick();
}
framesTicked += ticksToDo;
render();
Display.update();
}
if (DEBUG) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
} else {
Thread.yield();
}

} else {
// The window is not in the foreground, so we can allow other stuff to run and
// infrequently update
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}

Resources.manage();

if (Display.isVisible() || Display.isDirty()) {
// Only bother rendering if the window is visible or dirty
render();
}

Display.update();
}
}
}
It degrades gracefully to about 1/5th its requested framerate. Logic rate is fixed and is assumed to be quick enough to run at display framerate. This system is producing ultra smooth gameplay at 60Hz for us which degrades quite gracefully for slower machines.

Cas :)
Title: Re: Timer Comparison
Post by: basil on October 04, 2010, 16:12:53
*giggle

;D
Title: Re: Timer Comparison
Post by: basil on October 04, 2010, 16:19:16
sorry,  .. but that looks actualy not realy different from what i do too.

we might even come to the real problem with the timer. timers are not so stable but thats not too bad when you average the numbers in the end.

I think its more trouble when you look on Thread.sleep(1), as if we would get a true 1ms delay from that.  :-[
Thread.yield() wastes cpu to no good  :-\

now, how can we get a good solid frequency ?
Title: Re: Timer Comparison
Post by: princec on October 04, 2010, 19:41:38
Indeed, notice the DEBUG thing where I use Thread.sleep(1) instead of yield(). That's to stop Chaz's laptop overheating in Spain and shutting down. But in the released game it gives me an absolutely flat 60fps; sleep(1) occasionally drops 5 frames randomly for no explained reason.

Cas :)
Title: Re: Timer Comparison
Post by: basil on October 04, 2010, 19:51:10
aye, same here. tho' my other laptop is not in spain but downstairs.

my solution over thread.yield() is .. v-sync on, so far.
Title: Re: Timer Comparison
Post by: bobjob on October 04, 2010, 20:28:58
Have you tried mixing the "sleep" method
so if the need to wait is large use sleep(1) if its small, use yeild()
Title: Re: Timer Comparison
Post by: basil on October 04, 2010, 20:42:58
yep, it's probably the best trade-off.
as here http://andy-malakov.blogspot.com/2010/06/alternative-to-threadsleep.html its about finding the "sleep precision".
Title: Re: Timer Comparison
Post by: avm1979 on November 12, 2010, 17:26:28
I've been trying to get smooth timing for a little while, and finally got it working very smoothly (on Windows XP).

If the game loop is something like

<advance logic, render>
<sleep for 1/desired_fps minus however long the above took>

it will be fairly imprecise - I was experiencing very frequent jumps where a frame would take 2-3x longer than it's supposed to, just because the sleep() call took that much longer than expected.  So Thread.sleep(5) would return after 15+ ms.

The interesting part is, if you call Thread.sleep(1) often, it greatly improves timer precision.  Literally changing nothing else, and adding a new daemon thread that calls Thread.sleep(1) in an infinite loop, with no other interaction with the rest of the code, completely eliminated any jerkiness in the main game loop.

Weird, I know.  What's even more interesting is that this will help even if it's done in a separate process, not just a separate thread.
Title: Re: Timer Comparison
Post by: basil on November 12, 2010, 21:31:07
the daemon Thread.sleep (Integer.MAX_VALUE) or similar does the trick too.  ???
Title: Re: Timer Comparison
Post by: avm1979 on November 12, 2010, 21:45:10
the daemon Thread.sleep (Integer.MAX_VALUE) or similar does the trick too.  ???

Hmm.  I've tried setting it to Thread.sleep(2) and it was noticeably worse than sleep(1).  Haven't tried Integer.MAX_VALUE though, perhaps it behaves differently - I'll give it a shot tonight.

There's some native method you call in windows to increase timer precision.  So you usually call that method, call getTime, and then call another method indicating you no longer want increased precision.  The timer is system-wide, though, not just for your process.

So perhaps the timer precision isn't increased immediately, and takes a bit to kick in?  That would sort of explain this situation.  Sort of.