Loop Design - Low CPU Cost

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Rytz
Posts: 249
Joined: Wed Oct 25, 2006 6:05 am
Location: IL, USA
Contact:

Loop Design - Low CPU Cost

Post by Rytz »

Hey All,

I've been reading up on loop design for the last couple of days, searching forums and what not. Did some searching on this site to try and find out as much as possible before I start asking around on the forums.

As of right now, I'm using Sleep(1) to keep the CPU cost low on my "tight" loops. I have some GUI loops (for irrLicht) and some loops that use the typical "while (true){}" approach because they are waiting for flag variables to be set.

I'm curious to know what other folks are doing to keep their CPU usage down but still keep their program as efficient as possible. Any info or examples would be appreciated. Are there any cross-platform libs out there that work with handling system resources? I understand that handling system / CPU resources is OS dependent.

Thanks in advance for any info. Sorry if I missed a topic about this in the forum already.
Image
olivehehe_03
Posts: 157
Joined: Tue Mar 20, 2007 8:30 am

Post by olivehehe_03 »

I haven't had to worry about anything like this in my project yet, but I read about it somewhere a while back and it seemed pretty useful...

Basically, your main loop looks like this, not exactly like this, I know, but bear with me...

Code: Select all

	while(device->run())
	{
		if (device->isWindowActive())
		{
			driver->beginScene(true, true, video::SColor(255,0,0,255));
			doSomething();
			doSomethingElse();
			doSomeOtherStuff();
			smgr->drawAll();
			driver->endScene();
		}
	}
Now as you know, all that is happening every frame, which can sometimes give the CPU alot of things to do. What you can do though is change it around a little so that some things are only happeneing every second or third frame by doing something like this, again it's half C++, half pseudocode so yours would look diferent...

Code: Select all

int framecount = 0;
while(device->run())
	{
		if (device->isWindowActive())
		{
			driver->beginScene(true, true, video::SColor(255,0,0,255));
			framecount++;
			doSomething();
			if (framecount == 2)
			{
				doSomethingElse();
			}
			if (framecount == 3)
			{
				doSomeOtherStuff();
				framecount = 0;
			}
			smgr->drawAll();
			driver->endScene();
		}
	}
I hope thats not too hard to follow, but basically doSomething(); is running every frame, doSomethingElse(); is running every second frame and doSomeOtherStuff(); is running every third frame.

It might not seem like much written here, but think about how you would use it in a game. Less important things (like input and even AI and physics depending on your game) can be made to run every second or third frame, or even less often if you want, whereas more important things can be run every frame to make sure your game runs smoothly.

Well that was quite a post... :shock: Hope that helps
Tell me what you cherish most. Give me the pleasure of taking it away.
Rytz
Posts: 249
Joined: Wed Oct 25, 2006 6:05 am
Location: IL, USA
Contact:

Post by Rytz »

olivehehe_03 wrote:Well that was quite a post... :shock: Hope that helps
Thanks a lot for the post and insights.

What you put up there definitely wasn't confusing. Actually, you made me think more about what I'm trying to accomplish with my loops. I was so concerned with just trying to find a way to free up resources that I was missing the real objective: freeing up resources when actions are NOT being performed.

Sleep() is working really good (since I'm on windows - inactive program times are at 0% CPU now) but when I get to porting it over I'm going to have to add some defines for using a *nix based alternative (read some of them already during my research).

Thanks again for your post - it helped out a lot :).
Image
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

this isnt exactly what you need but it might help i gues http://www.mindcontrol.org/~hplus/graph ... _loop.html
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

"- Added sleep() methd to IrrlichtDevice, for pausing the Irrlicht process for a longer amount of time."

Changelog for 1.3
If you don't have anything nice to say, don't say anything at all.
Cocodrilo
Posts: 33
Joined: Fri Jul 21, 2006 9:27 pm
Location: Sweden, Eskilstuna
Contact:

Post by Cocodrilo »

Thanks olivehehe_03, quite usefull nice idea!
"Clicker"
Rytz
Posts: 249
Joined: Wed Oct 25, 2006 6:05 am
Location: IL, USA
Contact:

Post by Rytz »

roxaz wrote:this isnt exactly what you need but it might help i gues http://www.mindcontrol.org/~hplus/graph ... _loop.html
Thanks - it's definitely some good info on loop design. I might have to incorporate something like that later.
Luden wrote:"- Added sleep() methd to IrrlichtDevice, for pausing the Irrlicht process for a longer amount of time."

Changelog for 1.3
Well that will definitely help me with portability :D. I'll be testing that one out tonight.
Image
Vuen
Posts: 25
Joined: Tue Jul 11, 2006 8:03 am

Post by Vuen »

I don't know a whole lot about loop design. I just have one loop in which everything happens:

Code: Select all

    ITimer* timer = device->getTimer();
    u32 timelast = timer->getRealTime()-1;
    u32 timenow = timer->getRealTime();

    // Main loop
    while (device->run())
    {
        timenow = timer->getRealTime();
        time = timenow - timelast;
        timelast = timer->getRealTime();

        // Start the scene
        video->beginScene(true, true, SColor(255, 0, 0, 0));

        if (time > 0) {
            control->go(time);
            level->go(time);
        }

        // Draw everything
        scene->drawAll();
        gui->drawAll();

        // End the scene
        video->endScene();
    }
The go(time) tells the various components to do their stuff, and lets them know how much time has passed (so how far a character should be moved, etc.)
Rytz
Posts: 249
Joined: Wed Oct 25, 2006 6:05 am
Location: IL, USA
Contact:

Post by Rytz »

Vuen wrote:I don't know a whole lot about loop design. I just have one loop in which everything happens:

Code: Select all

    ITimer* timer = device->getTimer();
    u32 timelast = timer->getRealTime()-1;
    u32 timenow = timer->getRealTime();

    // Main loop
    while (device->run())
    {
        timenow = timer->getRealTime();
        time = timenow - timelast;
        timelast = timer->getRealTime();

        // Start the scene
        video->beginScene(true, true, SColor(255, 0, 0, 0));

        if (time > 0) {
            control->go(time);
            level->go(time);
        }

        // Draw everything
        scene->drawAll();
        gui->drawAll();

        // End the scene
        video->endScene();
    }
The go(time) tells the various components to do their stuff, and lets them know how much time has passed (so how far a character should be moved, etc.)
Well, my problem stems from having some network data "queues" in place that need to be continuously checked for new data. If there is no data, the loop basically comes down to "while(true){}" so it's burning a lot of CPU. I don't want the loop itself to be "paused" because I want the queue to be checked as frequently as possible.
Image
Vuen
Posts: 25
Joined: Tue Jul 11, 2006 8:03 am

Post by Vuen »

Yeah, you need something in there to make your thread sleep to give the rest of the computer a chance to do stuff. If you're drawing stuff to the screen, Irrlicht will do this automatically; otherwise, as Luden said, just go with Irrlicht's sleep method.
Rytz
Posts: 249
Joined: Wed Oct 25, 2006 6:05 am
Location: IL, USA
Contact:

Post by Rytz »

Thanks everyone for the advice and info :).
Image
Post Reply