Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » The age-old 100% CPU usage problem - but still no solution

Credits go to BAF, CGamesPlay, gnolam, Goalie Ca, GullRaDriel, Hard Rock, Kibiz0r, Kitty Cat, Kris Asick, Steve++, and Thomas Harte for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
The age-old 100% CPU usage problem - but still no solution
jamyskis
Member #6,557
November 2005
avatar

I started the game as usual, played it through three levels, lost, went back to the title screen and then exited the game cleanly. I know the profiler needs to be able to have used all of the functions available and it did get the chance...

Edit: I've attached a newly created profile which I created from playing the game for 15 minutes straight.

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

Goalie Ca
Member #2,579
July 2002
avatar

Well i'm not exactly sure what all those functions do and how the code is structured.. but it appears to me like there really is no bottleneck per say in your code. Just look at the cumulative time. If your program ran for 15 minutes none of those functions really ate all that much time.

 total     the average number of milliseconds spent in this
ms/call    function and its descendents per call, if this 
	   function is profiled, else blank.

So yours is actually listed in microseconds (us) per call. So if you add up the drawing commands that is not accounting for 7 minutes of total time (giving roughly 50% cpu usage).

Now i'm assuming your game loop is in the main function. If you took it out of main and put it in its own function then you could easily use the first table and fill in some of the gaps.

But it doesn't look like your code it slow at all. The "reported" cpu usage is probably coming from system scheduling.

-------------
Bah weep granah weep nini bong!

jamyskis
Member #6,557
November 2005
avatar

OK, I found out by using "top" the CPU usage of each process, and I found out something rather interesting - the game itself never takes up more than 60% of the CPU, even at the most intense moment. Xorg, on the other hand, shoots up when the game is running for whatever reason. I'm not sure how I can create a log which would test the same thing running in fullscreen mode. Anyway, I don't think I can hope for much better performance at this time, short of switching the whole thing to OpenGL (which I'd rather avoid given that it shouldn't really be necessary).

Anyway, thanks to all those that contributed with tips and help!

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

Don Freeman
Member #5,110
October 2004
avatar

I would just do something like:

1int main(int argc, char *argv[])
2{
3 allegro_init();
4 set_color_depth(32);
5 set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
6 set_color_conversion(COLORCONV_TOTAL);
7 text_mode(-1);
8 install_timer();
9 install_keyboard();
10 install_mouse();
11 textprintf(screen,font,0,0,makecol(255,255,255),"Press ESC to exit...");
12 show_mouse(screen);
13
14 bool quit = false;
15 bool redraw = true;
16
17 BITMAP *imageBuffer = create_bitmap(SCREEN_W,SCREEN_H);
18 clear_bitmap(imageBuffer);
19
20 while ( !quit )
21 {
22 if ( keypressed() )
23 {
24 if ( key[KEY_ESC] )
25 {
26 quit = true;
27 clear_keybuf();
28 }
29 redraw = true;
30 clear_keybuf();
31 }
32 if ( redraw )
33 {
34 redraw = false;
35 clear_bitmap(imageBuffer);
36 // Do drawing...
37
38 // End drawing...
39 blit(imageBuffer,screen,0,0,0,0,imageBuffer->w,imageBuffer->h);
40 }
41 else
42 {
43 // Update ai and yield unused time to system...
44 rest(1);
45 }
46 }
47 destroy_bitmap(imageBuffer);
48 return 0;
49}END_OF_MAIN()

This tells the system to yield until some event(redraw), which is in this case a key pressed, has occurred. It is up to you and your game logic to set this variable when you need to take control of the processing again. rest(0) and yield_timeslice never has seemed to work for me in windows or linux (several different flavors)...just pass rest(1) and I get the cpu to go to 0%...even during game play!

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

le_y_mistar
Member #8,251
January 2007
avatar

i havent done any game programming in a while, so take my question with a grain of salt.

Wouldn't it be better to use threads instead of loop+timer/frame rate counter?

-----------------
I'm hell of an awesome guy :)

Don Freeman
Member #5,110
October 2004
avatar

I don't think there IS a right or wrong answer to most of game programming...It is what is right for YOU. I have finally decided this after reading posts and books all of which contradict each other. It is ultimately up to you, and what you like. YOU are the one who has to code it and probably maintain it.
Each choice you have asked about has it's weakness and strengths. It is up to you to decide which problems and hurdles you wish to face...I DO know that threads can get you into a LOT of trouble if you are not careful...but you can do a lot of stuff you might not be able to do (at least no easily) without them...I would also imagine threads would be harder to debug as well...but I am certainly not a master of the art...:)

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

gnolam
Member #2,030
March 2002
avatar

Don Freeman said:

rest(0) and yield_timeslice never has seemed to work for me in windows or linux (several different flavors)...

That's because they're not supposed to reduce CPU usage. They yield to other processes. That's it.

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

Goalie Ca
Member #2,579
July 2002
avatar

Interesting though.. goalie's method of using semaphores seems to work quite well. If you need finer grain control implement your own semaphore class by wrapping one.

-------------
Bah weep granah weep nini bong!

jamyskis
Member #6,557
November 2005
avatar

Well, as I understand it, there have been three ways here suggested to reduce CPU usage:

(a) Use rest(1) somewhere in the game loop. The least effective, but the easiest to implement.

(b) Use the Semaphore library. More effective, but a bit more difficult to use. I may tackle this when I'm a little more confident with my programming.

(c) Get straight down to the grit of it and use threads. The most efficient method possible, but can be extremely unstable if you don't know what you're doing.

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

CGamesPlay
Member #2,559
July 2002
avatar

Quote:

(b) Use the Semaphore library. More effective, but a bit more difficult to use. I may tackle this when I'm a little more confident with my programming.

What's this "Semaphore library" you're talking about? You mean pthreads.

Quote:

(c) Get straight down to the grit of it and use threads. The most efficient method possible, but can be extremely unstable if you don't know what you're doing.

I fail to see how this reduces CPU usage. In fact, it increases CPU usage, as now you have two busy loops running around :P

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

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

Thomas Harte
Member #33
April 2000
avatar

Quote:

Well, as I understand it, there have been three ways here suggested to reduce CPU usage:

My method is, as it has always been:

  • do a frame draw

  • read a counter, compute number of milliseconds/whatever since last here in loop

  • if now one or more logic ticks behind, do that many logic ticks

  • otherwise sleep for the number of milliseconds/whatever left before next update

In SDL I use SDL_GetTicks which returns the number of milliseconds since the app started. In Allegro I have a second thread that updates a timer that is much coarser than milliseconds but gets the job done. My ChristmasHack '05 entry, Nuclear Attack! (Windows, OS X) is one example. On a virtualised copy of Windows 2000 on my MacBook Pro, it uses less than 5% of one CPU core.

 1   2 


Go to: