Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » my game uses 90% CPU

This thread is locked; no one can reply to it. rss feed Print
 1   2 
my game uses 90% CPU
koless
Member #4,996
September 2004

my game uses 90% CPU how to prevent it?

1int main(){
2 
3 FInitializeGame(); //game initialization
4 
5 TPanama_Joe * joe;
6 joe = new TPanama_Joe(224,248,0,typejoe);
7 TBoard gameboard(joe->get_board_id());
8 bool game_start=true;
9 unsigned int intro_counter=0;
10
11 gameboard.Load_intro();
12
13 while (!key[KEY_ESC])
14 {
15 clear(buffer);
16 while (main_counter>0){
17
18 if(game_start==true){
19
20 gameboard.gamelevel=0;
21 if(key[KEY_1]) gameboard.gamelevel=1;
22 else
23 if(key[KEY_2]) gameboard.gamelevel=2;
24 else
25 if(key[KEY_3]) gameboard.gamelevel=3;
26 else
27 if(key[KEY_4]) gameboard.gamelevel=4;
28
29 if (gameboard.gamelevel!=0) {
30 game_start=false;
31 joe->joeloadpos_disc(gameboard.gamelevel);
32 joe->joesavepos();
33 gameboard.Load_(joe);
34
35 }
36
37 intro_counter++;
38 if(intro_counter>60) intro_counter=0;
39
40 }else
41 if(joe->joemove(gameboard.CLlist)==true){
42 gameboard.Load_(joe);
43 joe->joesavepos();
44 }
45
46 gameboard.CLlist.moveobject(typeskull);
47 gameboard.CLlist.moveobject(typeskull_x2);
48 gameboard.CLlist.moveobject(typejumpinskull);
49 gameboard.CLlist.moveobject(typejumpinskull_x2);
50 gameboard.CLlist.moveobject(typespider);
51 gameboard.CLlist.moveobject(typespider_x2);
52 gameboard.CLlist.moveobject(typesnakeR);
53 gameboard.CLlist.moveobject(typesnakeL);
54
55 if (key[KEY_F5]){
56 FCreateBoard();
57 if((joe->itemsCTR.searchitem(typetorch))==true)
58 gameboard.objects_visible=true;
59 gameboard.display_objects(gameboard.objects_visible);
60 gameboard.change_board_color();
61 }
62
63 if (key[KEY_F12] || joe->joegameover==true){
64
65 delete joe;
66 joe = new TPanama_Joe(224,248,0,typejoe);
67 game_start=true;
68 gameboard.Load_intro();
69
70 }
71
72
73 TPanama_Joe::animupdate();
74 TScroller::animupdate();
75 TFlames::animupdate();
76 TBridge::animupdate();
77 TSpider::animupdate();
78 TLaser::animupdate();
79 TTorch::animupdate();
80 main_counter--;
81
82 }
83 
84 
85 joe->itemsCTR.draw();
86 gameboard.draw();
87 joe->draw();
88 
89 if(game_start==true){
90
91 draw_sprite(buffer,(BITMAP*)data[logo].dat,165,85);
92 draw_sprite(buffer,(BITMAP*)data[logobottom].dat,0,400);
93 if(intro_counter>30){
94 writetext("PRESS 1,2,3 or 4 TO",250,240);
95 writetext("START GAME",285,255);
96 }
97
98 }
99
100
101
102 acquire_screen();
103 blit(buffer,screen,0,0,0,0,640,480);
104 release_screen();
105
106 }
107
108 delete joe;
109 FQuitGame(); //Quit game
110 
111}
112END_OF_MAIN();

Jonatan Hedborg
Member #4,886
July 2004
avatar

First of all, use the [CODE][/CODE] tags (only in non-caps)
Secondly, for your program to be able to take less than maximum CPU, it needs to use rest(1) or somesuch function.

-------
Sweden: Free from the shackles of Democracy since 2008-06-18!

Chris Katko
Member #1,881
January 2002
avatar

Long answer:
You game will naturally try to take as much CPU time as possible. This isn't exactly a problem, because the more CPU usage, the faster your game runs, and the more you can do in a second. However, if you do want to reduce it, use the aforementioned rest() function. Use rest(0) to yield all the extra time back to the operating system.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Ceagon Xylas
Member #5,495
February 2005
avatar

Call it at the end of your game loop [after logic and drawing sequences.]

while(!game_over) {
  game_logic.update();
  game_logic.draw_buffer();
  rest(0);
}

Elverion
Member #6,239
September 2005
avatar

Something like...

1int main()
2{
3 Init();
4
5 while( !quit )
6 {
7 if (key[KEY_ESC]) {
8 quit=true; }
9
10 while(speed_counter)
11 { // logic "step"
12
13
14 --speed_counter;
15 yield_timeslice();
16 }
17
18 // redraw
19 ScreenSystem->draw_flip();
20 fps++;
21 yield_timeslice();
22 rest(1);
23 }
24
25 return 0;
26}
27END_OF_MAIN();

should work pretty well. Using the yield_timeslice() function will mean your program will yield it's processor usage if some other program needs it more, otherwise it will still use 100%. This means that your program might look like it's using 100% of the processor, but in reality most of it is going to waste unless it's actually needed. The rest(1) part will actually make the program appear to use less CPU.

--
SolarStrike Software - MicroMacro home - Automation software.

CGamesPlay
Member #2,559
July 2002
avatar

Quote:

Using the yield_timeslice() function will mean your program will yield it's processor usage if some other program needs it more, otherwise it will still use 100%.

Recently yield_timeslice was changed to rest(1), so it will cause 0% CPU usage.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Elverion
Member #6,239
September 2005
avatar

Hmm, didn't know that. When did this happen? Is this in the stable 4.2.0?

--
SolarStrike Software - MicroMacro home - Automation software.

A J
Member #3,025
December 2002
avatar

Quote:

Recently yield_timeslice was changed to rest(1), so it will cause 0% CPU usage.

rest(1) is not yielding, its sleeping. When did someone decide to redefine the meanings of words.

___________________________
The more you talk, the more AJ is right. - ML

Kitty Cat
Member #2,815
October 2002
avatar

rest(0) does the same thing as yield_timeslice, which does not save the CPU (it'll come right back to your program when nothing else wants it). Using rest(1) is what you want, but you only want to call it when you're not falling behind.

while(playing)
{
   while(counter <= 0)
      rest(1);

   while(counter > 0)
   {
      do_logic();
      --counter;
   }

   draw();
}

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

CGamesPlay
Member #2,559
July 2002
avatar

I thought we had a big discussion and it was decided that: yes, yield_timeslice is by semantics rest(0), but everyone actually wants rest(1), so it was changed...

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Leverton
Supreme Loser
January 1999
avatar

/* sys_directx_yield_timeslice:
 *  Yields remaining timeslice portion to the system.
 */
static void sys_directx_yield_timeslice(void)
{
   Sleep(0);
}

I believe at one point during the WIPs, it was changed to Sleep(1). Yielding is not the same as resting for 1 msec and it's a good thing that it is still Sleep(0).

However, if you look back at news, you'll see "Deprecated yield_timeslice in favour of rest(0)." I don't remember why; maybe it had to do with differences in cross platform behaviour. But whatever, I think yield_timeslice makes a lot more sense then manually calling rest(0). If it was truly deprecated just because people wanted 0% CPU usage, that's stupid. Yield is yield. It's not rest.

Milan Mimica
Member #3,877
September 2003
avatar

Quote:

Recently yield_timeslice was changed to rest(1), so it will cause 0% CPU usage.

Did not!
yield_timeslice was declared deprecated, and it's implemented the same as rest(0), i.e. it won't reduce CPU usage, but just relinquish the processor.

Tomek Kozera
Member #6,507
October 2005
avatar

I don`t know pretty much about writing games, so whould someone explain to me what would rest(0) do? It would rest 0 miliseconds so... I guess, that since is rests even for 0 time, then the program would give back the processor to other processes. So it`s like forcing the game to give the prcessor time to other applications without acutally slowing down the game. Is that correct?

An in what context is 'yield' used here? I get a bit confused, it seems that I don`t know all the meanings of this word.

Milan Mimica
Member #3,877
September 2003
avatar

On Unixes, rest(0) is implemented as sched_yield. It will give back the processor to other processes, but it will also "slow down" your game because it will resume after more than 0 ms. It depends on the mood of other processes. However, yielding will be forced by OS every now and then. On linux 2.6.x it depends of kernel config CONFIG_HZ.

Thomas Harte
Member #33
April 2000
avatar

Quote:

This isn't exactly a problem, because the more CPU usage, the faster your game runs, and the more you can do in a second.

This is a problem. If you don't put the CPU to sleep when it could be sleeping then you require that the processor be run constantly at it's highest frequency. All laptops and many well designed desktops cut power to the CPU when it is sleeping a lot, e.g. by reducing the clock speed. Once the power is cut heat output decreases and often fans can be slowed down or switched off, reducing noise output. If your program uses 100% CPU just because it can then it will probably not stay on those machines for long.

Here is how I achieve non-100% CPU usage with Allegro (in this example, limiting to 70 fps):

1volatile int scupdate=0;
2void update280()
3{
4 scupdate++;
5}
6END_OF_FUNCTION(update280);
7 
8...
9{
10 /* at startup */
11 LOCK_FUNCTION(update280);
12 LOCK_VARIABLE(scupdate);
13 install_int_ex(update280,BPS_TO_TIMER(280));
14 
15 
16 /* in game loop */
17 skipframe = false;
18 if(scupdate < 4)
19 {
20 rest(((4-scupdate)*1000)/280);
21 scupdate -= 4;
22 }
23 else
24 {
25 if(scupdate > 4)
26 {
27 framecount++;
28 if(framecount&7) skipframe = true;
29 }
30 if(scupdate > 7) scupdate = 0; else scupdate -= 4;
31 }
32}

EDIT: code fixed.

Birdeeoh
Member #6,862
February 2006
avatar

I don`t know pretty much about writing games, so whould someone explain to me what would rest(0) do? It would rest 0 miliseconds so... I guess, that since is rests even for 0 time, then the program would give back the processor to other processes. So it`s like forcing the game to give the prcessor time to other applications without acutally slowing down the game. Is that correct? An in what context is 'yield' used here? I get a bit confused, it seems that I don`t know all the meanings of this word.

Tomek -

rest() in allegro, which is also sleep() on unices and Sleep() on Windows, tells the operating system to put the process to sleep for the specified number of milliseconds.

The concept of "sleep" is threading/operating system speak that means, in plain English, "Hey, operating system - I'm done for now. Let other programs have the CPU, and don't bother me again for X milliseconds."

The concept of "yield" is threading/operating system speak that means, in plain English, "Hey, operating system - I can stop what I'm doing right now so you can let other programs do stuff they need to do. BUT, if noone else has any work to do, then please let me know so I can keep going"

That's what rest(0) or the windows Sleep(0) do. They tell the o/s to give the CPU to others, but if noone else wants/needs it, let your process have it back.

That's why rest(0) won't accomplish what you're going for. The CPU will still stay at 100% because your program is still working fulltime - it's just "playing nice" with everyone else.

If you actually rest(1), you are telling the operating system to not even let you have the CPU until at least 1ms has passed. Therefore, the CPU usage WILL actually drop. With today's CPU speeds, 1 millisecond is an eternity. If every millisecond you wake up, do a few hundred thousand instructions, then go back to sleep, you're barely using the CPU.

I hope that helps you understand the terminology better!

On a related note, as someone pointed out already, some desktops and many/most laptops the system crank up the fans when the CPU is at full usage for a long time. Other power-management side-effects can also occur. This is why going full throttle is bad form unless you actually have to. I have a P4 3.0ghz in a laptop that is very quiet when at rest, but when something is using 100% cpu the thing SCREAMS. I play hard core 3d games on my laptop and expect them to be using full resources all the time - I wear headphones. But other games that are poorly designed don't last long on my computer. I once ran across a KICK ASS solitaire suite that I loved, but it used 100% CPU. I'm sorry, there's no way you actually need 3 billion instruction cycles a second for me to play free cell. ;)

[url http://developer.berlios.de/projects/openlayer/]OpenLayer[/url is an OpenGL accelerated 2D library for fast and easy graphics development under Allegro

Tobias Dammers
Member #2,604
August 2002
avatar

The best way would be using thread wake-up events, based on a timer. In short, you set up a timer to wake your main thread at regular intervals (with each timer click). After you are done drawing a frame and updating logic, make the main thread sleep until signalled again. It will use 0% cpu until the timer ticks again, but will continue if it already has.
Unfortunately, allegro doesn't have a mechanism to support this, so you'll have to use platform-specific api to do this.
In windows, one would have 2 threads, a main thread and a timer thread. The timer thread increments the counter and activates an event (thereby waking up the main thread if necessary). The main thread updates logic, draws, sleeps until timer event, and repeats.

If you don't want to multi-thread, use the rest() approach.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Milan Mimica
Member #3,877
September 2003
avatar

What's the difference between your approach and this?

Kitty Cat
Member #2,815
October 2002
avatar

Because that doesn't rest at all :P. But seriously..

while(timer <= 0)
   rest(1);

causes the thread to rest anywhere between 1ms and 10ms per call, which isn't very accurate, and it cuases the program to rest-check-rest-check-etc (which takes some, if negligible, CPU time) until its ready, instead of just staying down and letting the OS wake the thread up on time.

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

Milan Mimica
Member #3,877
September 2003
avatar

How do you implement this timer thread?

Tobias Dammers
Member #2,604
August 2002
avatar

1. Write a thread function for the timer thread, which sleeps for the desired amount of time, then sets an event.
2. Spawn a thread from your main thread.
3. Use a waiting function in the main thread to suspend until the timer event is signalled.

For more details:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createevent.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/setevent.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitforsingleobject.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp
These should get you started.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Kitty Cat
Member #2,815
October 2002
avatar

Hello, Windows-only only land. Nice to see you.

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

Tobias Dammers
Member #2,604
August 2002
avatar

Yay, hello there. Haven't done any multithread programming on other platform, so I guess someone else should do the appropriate googling.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

GullRaDriel
Member #3,861
September 2003
avatar

Pthread is cross platfrom.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

gnolam
Member #2,030
March 2002
avatar

But it is also a pain in the ass to build and use on non-*n?x platforms, or at least so I've heard.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

 1   2 


Go to: