tags:

views:

342

answers:

6

EDIT:

I would like to thank you all for the swift replies ^^ Sleep() works as intended and my CPU is not being viciously devoured by this program anymore! I will keep this question as is, but to let everybody know that the CPU problem has been answered expediently and professionally :D

As an aside to the aside, I'll certainly make sure that micro-optimizations are kept to a minimum in the face of larger, more important problems!

================================================================================

For some reason my program, a console alarm clock I made for laughs and practice, is extremely CPU intensive. It consumes about 2mB RAM, which is already quite a bit for such a small program, but it devastates my CPU with over 50% resources at times.

Most of the time my program is doing nothing except counting down the seconds, so I guess this part of my program is the one that's causing so much strain on my CPU, though I don't know why. If it is so, could you please recommend a way of making it less, or perhaps a library to use instead if the problem can't be easily solved?

/* The wait function waits exactly one second before returning to the *
 * called function.                                                   */     
 void wait( const int &seconds )
 {
 clock_t endwait; // Type needed to compare with clock()
 endwait = clock() + ( seconds * CLOCKS_PER_SEC ); 

 while( clock() < endwait ) {} // Nothing need be done here.
 }

In case anybody browses CPlusPlus.com, this is a genuine copy/paste of the clock() function they have written as an example for clock(). Much why the comment //Nothing need be done here is so lackluster. I'm not entirely sure what exactly clock() does yet.

The rest of the program calls two other functions that only activate every sixty seconds, otherwise returning to the caller and counting down another second, so I don't think that's too CPU intensive- though I wouldn't know, this is my first attempt at optimizing code.

The first function is a console clear using system("cls") which, I know, is really, really slow and not a good idea. I will be changing that post-haste, but, since it only activates every 60 seconds and there is a noticeable lag-spike, I know this isn't the problem most of the time.

The second function re-writes the content of the screen with the updated remaining time also only every sixty seconds.

I will edit in the function that calls wait, clearScreen and display if it's clear that this function is not the problem. I already tried to reference most variables so they are not copied, as well as avoid endl as I heard that it's a little slow compared to \n.

+6  A: 

This is called a busy-wait. The CPU is spinning its wheels at full throttle in the while loop. You should replace the while loop with a simple call to sleep or usleep.

I don't know about the 2 MB, especially without knowing anything about the overall program, but that's really not something to stress out over. It could be that the C runtime libraries suck up that much on start-up for efficiency reasons.

Marcelo Cantos
Even with a sleep(), this is still called a busy wait, but it will definitely solve your CPU problem.
Neil Whitaker
Eh? Sleeping for a specified interval (when a specified interval is what you're trying to wait for, rather than a specified condition) is not a busy wait.
Tyler McHenry
@neilwhitaker1, what is your understanding of the term "busy wait"? `sleep` puts the calling thread to sleep (hence the name) and wakes it up when it's time; there is nothing busy about it.
Marcelo Cantos
I think @neil's comment was based on adding a call to `sleep(n)` to the while loop where `n` is less than `seconds` (like Per's answer), rather than trashing the whole `wait` function and using `sleep` in its place.
Nick Meyer
+1, Nick; thanks for pointing that out. I've adjusted the answer to avoid this possible confusion.
Marcelo Cantos
+2  A: 

You're spinning without yielding here, so it's no surprise that you burn CPU cycles.

Drop a

  Sleep(50);

in the while loop.

500 - Internal Server Error
+14  A: 

This:

while( clock() < endwait ) {} 

Is not "doing nothing". Certainly nothing is being done inside the while loop, but the test of clock() < endwait is not free. In fact, it is being executed over and over again as fast as your system can possibly handle doing it, which is what is driving up your load (probably 50% because you have a dual core processor, and this is a single-threaded program that can only use one core).

The correct way to do this is just to trash this entire wait function, and instead just use:

sleep(seconds);

Which will actually stop your program from executing for the specified number of seconds, and not consume any processor time while doing so.

Depending on your platform, you will need to include either <unistd.h> (UNIX and Linux) or <windows.h> (Windows) to access this function.

Tyler McHenry
And in Windows, it's `Sleep`.
GMan
Additionally, in *nix the argument to sleep is in seconds, and on Windows the argument to Sleep is in milliseconds.
Nathan Ernst
+2  A: 

The while loop is keeping the processor busy whenever your thread gets a timeslice to execute. If all you wish is to wait for a determined amount of time, you don't need a loop. You can replace it by a single call to sleep, usleep or nanosleep (depending on platform and granularity). They suspend the thread execution until the amount of time you specified has elapsed.

Alternatively, you can just give up (yield) on the remaining timeslice, calling Sleep(0) (Windows) or sched_yield() (Unix/Linux/etc).

If you want to understand the exact reason for this problem, read about scheduling.

jweyrich
+1  A: 

while( clock() < endwait ) { Sleep(0); } // yield to equal priority threads

renick
Just a note, `Sleep(0)` is Windows specific.
jweyrich
+3  A: 

The CPU issue has been answered well. As for the memory issue, it's not clear what 2 MB is actually measuring. It might be the total size of all the libraries mapped into your application's address space.

Run and inspect a program that simply contains

int main() { for (;;) }

to gauge the baseline memory usage on your platform.

Potatoswatter
Odd result: This program uses *more* resources than my clock, which should not be possible. Any reason as to why this may be?
SoulBeaver
@soul: possibly because the original program causes a system call when it calls `clock`, and the kernel uses that as an opportunity to sleep.
Potatoswatter
You need a semicolon after the `for`.
GMan