Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Limit of usage of the timers

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Limit of usage of the timers
tobing
Member #5,213
November 2004
avatar

The overhead from these function calls is so small that I can't measure it.

I don't use these high precision timers for game speed, but to give some time back to the OS, more precisely the time remaining to the next frame when all the work has been done for this frame. In that context it is very reasonable to ask for precision of 1ms.

Kitty Cat
Member #2,815
October 2002
avatar

Quote:

In that context it is very reasonable to ask for precision of 1ms.

Not really.. not unless your game is running at more than 100LPS (log frames per second). 0.01th of a second for jitter isn't that big of a deal.

That said, you don't even have to rest at all for a CPU intensive game.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

tobing
Member #5,213
November 2004
avatar

True, but for a CPU intensive game only. My game is expected to use only very little CPU, even at higher logical speed. I just like to be nice with my game, and I like to save my laptop from using power when it is not really necessary.

Kitty Cat
Member #2,815
October 2002
avatar

Usually when a game isn't CPU intensive, it doesn't need that extra precision. The time jitter is reduced/removed by the speedy execution.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

tobing
Member #5,213
November 2004
avatar

Theoretically, yes. That's what I thought before. Then I just saw that my program would use much more CPU than expected, and that's where I started my investigations. So my finding is that calling timeBeginPeriod(1) when using rest(1) solved the problem essentially.

Evert
Member #794
November 2000
avatar

How about using something equivalent to

timeBeginPeriod(n);
rest(n);
timeEndPeriod(n);

or perhaps something like timeBeginPeriod((n+1)/2)? In that way, you don't increase the granularity of the timer to more than it needs to be and keep the benefits that it offers... I think. Of course, the most common case would be rest(1), where this wouldn't actually change anything.

tobing
Member #5,213
November 2004
avatar

I don't know what other side effects the timeBeginPeriod(n) would have. I would definitely not like to have it influence other timers around. So I think that calling timeBeginPeriod(1) only increases precision, so it doesn't harm. Calling it with other values might decrease precision in case the application has called timeBeginPeriod(1) before. I would not appreciate such a behaviour...

Edit: Before calling timeBeginPeriod you have to use timeGetDevCaps to determine valid values. The following code is from MSDN:

#define TARGET_RESOLUTION 1         // 1-millisecond target resolution

TIMECAPS tc;
UINT     wTimerRes;

if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) 
{
    // Error; application can't continue.
}

wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
timeBeginPeriod(wTimerRes);

I haven't looked into how timers are created in allegro, but if it is using timeSetEvent it will be affected by timeBeginPeriod also. So it might also be a good idea to put a call of timeBeginPeriod(1) into allegro's init_timer() function?

Evert
Member #794
November 2000
avatar

Quote:

I don't know what other side effects the timeBeginPeriod(n) would have. I would definitely not like to have it influence other timers around.

It shouldn't affect other applications at any rate... I'm not sure about other threads though, but that's something that would have to be tested.

Quote:

So I think that calling timeBeginPeriod(1) only increases precision, so it doesn't harm. Calling it with other values might decrease precision in case the application has called timeBeginPeriod(1) before. I would not appreciate such a behaviour...

Remember that this is for rest() only though. If you call rest(10), does it really make sense to set the resolution to 1 if 10 (or 5) would probably do just as well for that case?

Quote:

but if it is using timeSetEvent it will be affected by timeBeginPeriod also. So it might also be a good idea to put a call of timeBeginPeriod(1) into allegro's init_timer() function?

Probably, yes. I don't know how this is done in Windows though... I can probably look at the code (but not test it) this evening.

tobing
Member #5,213
November 2004
avatar

I'll look into the code this weekend, and I'll test calling timeBeginPeriod(1) from within init_timer().

OK. So here's my findings:

When I call timebeginPeriod(1) in the beginning of my program, or inside install_timer() then overall CPU usage increases (sometimes drastically). So some objections made are valid: requesting higher accuracy does cost something.

So then I tried some other places to put this call, but the only place where it does good - and really decreases CPU usage - is inside of the implementation of rest(), which is exactly what I requested some time ago.

Evert: Should I send you the code again, this time with some improved error handling? It is not much, only checking the return value of timeBeginPeriod() to decide if timeEndPeriod() has to be called or not.

Evert
Member #794
November 2000
avatar

Quote:

Evert: Should I send you the code again, this time with some improved error handling? It is not much, only checking the return value of timeBeginPeriod() to decide if timeEndPeriod() has to be called or not.

Please do!
Also, if you could check if Allegro uses timeSetEvent and would be affected by calling timeBeginPeriod()?

tobing
Member #5,213
November 2004
avatar

The function 'timeSetEvent' is not used in allegro. What is used is a call to 'SetEvent' using 'timer_stop_event = CreateEvent(...)' in wtimer.c:222. As far as my program has shown, the call to timeBeginPeriod(1); added in tim_win32_rest(...) does not affect that. Well, calling timeBeginPeriod(1); from my main program has some effects, so that might have undesirable influence here.

This is the updated code section in wtimer.c:

1/* tim_win32_rest:
2 * Rests the specified amount of milliseconds.
3 */
4static void tim_win32_rest(unsigned int time, AL_METHOD(void, callback, (void)))
5{
6 unsigned int start;
7 unsigned int ms = time;
8 
9 const MMRESULT rc = timeBeginPeriod(1);
10 if (callback) {
11 start = timeGetTime();
12 while (timeGetTime() - start < ms)
13 (*callback)();
14 }
15 else {
16 Sleep(ms);
17 }
18 if( rc == TIMERR_NOERROR )
19 timeEndPeriod(1);
20}

Maybe I should also send this to the mailing list (AD)?

Evert
Member #794
November 2000
avatar

Quote:

Maybe I should also send this to the mailing list (AD)?

Please do. Or, you can use the tracker on Allegro's sourceforge page.

tobing
Member #5,213
November 2004
avatar

Elias
Member #358
May 2000

Why not just put time_begin_period into allegro_init? Surely calling it only once at startup would cause less overhead than calling it everytime rest() is called.. or am I missing something?

--
"Either help out or stop whining" - Evert

tobing
Member #5,213
November 2004
avatar

I have tried that. The overall performance decreases actually, which surprised me of course. Explanantion is probably that the call does have some side effects, which cause more overhead in other functions. So that's the reason I have left it at putting the calls into rest() only.

Elias
Member #358
May 2000

Ah, makes sense then. Probably should add a comment telling about that..

--
"Either help out or stop whining" - Evert

tobing
Member #5,213
November 2004
avatar

Finally I got some test project together, which contains my current game framework including the game loop. This can serve as performance benchmark (how many balls do use how much cpu time), but also as an example of a game framework and a game loop. Basically, the game loop is taken from Lennart Steinke's book 'Spieleprogrammierung' in bhv Verlag.

There's a MSVC7.1 project file included, but no makefile (the last makefile I have written is 8 years ago...), and you have to include the allegro library to the linker statement (because I'm using my allegro project file, which inplies automatic linkage in the Visual Studio). If someone has a working makefile, you might post it here, so I can include it in the archive eventually...

 1   2 


Go to: