I'm back on the forum after a long absence due to (ahem!) illness, this time with an age old question which I see posted on this forum dozens of times but never really explained in a way I could understand. I've managed to fix the speed of my game, but performance is choppy because, for whatever reason, the CPU is taking up 100% of the time. I've made the game logic updates event-based, so they are called by an interrupt at regular intervals, and I've tried cutting out the game_display() (the function that contains all the code dealing with drawing the screen) completely to see if the drawing was taking too much time (it throws around 50-60 sprites at a time so it would be understandable, especially under Linux with no GFX hardware acceleration). Without any drawing functions, the game still swallows up 100% CPU time.

This is the main.cc as it stands:

1

/* Open Invaders

2

* (c) 2006 Darryl LeCount

3

*

4

*

5

* This program is free software; you can redistribute it and/or modify

6

* it under the terms of the GNU General Public License as published by

I've been playing with this for months and am just about ready to chuck it in and delete the lot. Can anyone give me a hand as to why I can't stabilise the frame rate and drop the CPU usage? If there's anything else I should paste in let me know.

Thanks!

Darryl

__________________________________________________________________In a world without fences and walls, who needs Windows and Gates?http://www.jamyskis.net

Woops just noticed you had a rest. Drop vysc. I believe some forum posters mentioned that vysnc would allow timing, but also consume 100% cpu usage while it did. As vsyc doesn't return until its done, rest literally only gets called 60 times per second, if that.

[edit2]There was also just recently a post on sample game loops, though it's not 100% relevant, and looking through it I didn't really find any stellar examples (most of it is psuedo code) it might help. http://www.allegro.cc/forums/thread/590871

[edit3]If neither of these helps, I'll take my GWARA Tins entry, and modify it so it doesn't use 100% cpu and post the updated code. Or try to at least. Just let me know.

Your frame dropping algorithm fails to take into account if the logic processing is taking too long. Frame dropping cures when the rendering takes too long, but if the logic is taking to long, more logic updates will be requested while logic is being processed, resulting in potentially large amounts of logic loops per frame, which is possibly the source of your framerate troubles and your 100% CPU usage.

What you need to do is put a limit to how many logic updates you'll allow on one game loop. 4 is a good limit. This prevents your logic loop from over-processing, which will result in slow-down if your system can't handle the amount of logic that needs to be processed, but that will be true of any game using fixed-time logic.

You may also want to check and make sure you're not running 32-bit graphics. 16-bit graphics will run almost twice as fast as 32-bit on any system. Also, avoid strange colour depths such as 15-bit or 24-bit which may invoke compatability layers if your video card can't handle them by default.

Also, vsync() will not eat up so much CPU time that you'll get 100% usage so long as you have rest() or Sleep() statements to give time back to the OS. However, you should place your rest() statement immediately after rendering, not right before vsyncing.

While your program is running it counts towards using cpu's. Yielding/resting will tell the operating system to stop running your program for the time being. While its doing nothing it is using 0%.

Here is a fix that shouldn't affect any thing. It works exactly the same except that when the count is 0 it returns to the operating system. When the count goes back above 0 it wake the process up. Just replace sdl_semaphore with one from your operating system be it windows or linux (i can help you if you need).I used the evil sdl because allegro has nothing similar/portable IIRC.

//the timer function. basically SemPort will "increment" the tick variable.
Uint32 SDLTimer_Callback(Uint32 interval, void* param){
SDL_SemPost(sleepSemaphore);//will wake up the other thread. "increments" the countreturn interval;}//the main loopwhile(!quitMe ){
SDL_SemWait(sleepSemaphore);//sleeps if count = 0, when it is no longer 0 it wakes up and decrements the count
gameLogic();}

edit: i should explain that sleepSemaphore is basically just a counter. It is used for synchronizing between threads but this works perfectly fine in a situation like this. This uses < 1% of my cpu in most cases (also opengl for hardware drawing helps!)

edit2: rest(1) doesn't sleep 1ms esp on windows. Windows is not a real-time operating system. You'll only get accuracy to ~ 10ms or so. SO like 10ms 20ms 30ms etc...

Actually that's pretty good thing. Windows is the only platform (other than embedded) that doesn't support pthreads). The only reason why i didn't use sem_wait was because almost all n00bs who post use windows. It's a fact! But I hope that works for vc (or whatever they used).

If it does... then its about time to make a wiki entry and end this line of threads once and for all!

The only reason why i didn't use sem_wait was because almost everyone who posts uses windows.

Fixed

A game with real-time performance requirements using 100% CPU time isn't a problem in itself. In fact, when your game yields its current timeslice to the OS, it must wait until the OS's next round of scheduling. That may be ok for tic-tac-toe. How demanding do you think your game will be on the CPU?

Putting the thread to sleep and then waking it up is not a problem. In fact since timer is run in a seperate thread it gets woken up, then you have to reschedule the main loop thread anyways. When the sem_post occurs it changes the threads state to ready... the same as it would be if it was pre-empted because its time slice expired.

Windows is not real-time, not anything close... so you have to live with what you get i suppose. I guess this is why the thread about delta timing came up where you use getTimeOfDay() and find out how much time really elapsed (in milliseconds). But there are problems with pausing and scheduling (if you're relying upon small differences rather than averages then you'd need to lock everything up during that computation sequence)

OK, this is the third time I've typed this answer...Allegro.cc keeps logging me out for whatever reason and the answer gets lost...

Anyway, the only solution I've found that effectively yields the CPU is to omit the vsync() and include rest(1). However, update_logic() was then executed so seldomly that frames_missed got really high and as a result I had frame rates of around 1 frame every five seconds. I tried limiting frames_missed to four, but that just made the game extremely slow and extremely choppy, although CPU usage was at about 80% there.

Edit: I've just noticed that the title screen, which displays a large sprite in the middle of the screen, two textout_ex's and 500 pixel "stars" in the background is chomping up 90% CPU time on an Athlon 2400 - is Allegro's Linux graphics driver really that bad?

Edit 2: OK, I have the game running doing everything except blitting the backbuffer to the screen, and it runs at a fairly respectable 45% CPU usage. As soon as I do blit(display,screen,0,0,0,0,800,600) though, it just flats out to 90-95%...isn't there a faster way to blit display to screen?

__________________________________________________________________In a world without fences and walls, who needs Windows and Gates?http://www.jamyskis.net

Thanks - I'll give it a go, if only to bring the 45% down a bit. Still, I'd love to know why a single Allegro function call is chomping up 50% of my CPU time. Just chopping out that single blit call brought it down from 95% to 45%...

__________________________________________________________________In a world without fences and walls, who needs Windows and Gates?http://www.jamyskis.net

I'll give it a go, if only to bring the 45% down a bit. Still, I'd love to know why a single Allegro function call is chomping up 50% of my CPU time. Just chopping out that single blit call brought it down from 95% to 45%..

What i actually mean is that how can you really be sure you're actually spending that much cpu time in a single blit. I really doubt it.

Rest is not an accurate function. Windows is not a real-time operating system (though linux has patches). This means that if you rest(1) it may take 20ms to return to the program or it may return right away, execute a loop, go to sleep, return right away, etc... This is all scheduling dependant.. so many adding a blit changes how windows schedules your process.

A profiler will actually tell you how much time you spend in each function. In my example code above. i have a simple rectfill.. When i change rectfill to cover the entire screen (with a gray colour) my cpu usage becomes:

real 1m0.350s
user 0m0.884s
sys 0m0.052s

So.. there's some expense in rectfill. Blitting should be comparable in runtime.

Now gprof (my profiler!) outputs: Clearly you can see that after just a

pmask_load_func obviously belongs to pmask although I can't imagine why it reports it as taking up 81.27% of the processing time. Commenting out the call to collision_detection() (which contains the only references to pmask.h in the entire loop) does nothing for the performance, commenting out the blit call reduces usage by around 50%.

__________________________________________________________________In a world without fences and walls, who needs Windows and Gates?http://www.jamyskis.net