Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

does while loop always take full CPU usage?

I need create a server side game loop, the problem is how to limit the loop cpu usage.

In my experience of programming, a busy loop always take maximal CPU usage it could. But I am reading the code of SDL(Simple DirectMedia Layer), it has a function SDL_Delay(UINT32 ms), and it has a while loop, does it take max cpu usage, if not, why?

https://github.com/eddieringle/SDL/blob/master/src/timer/unix/SDL_systimer.c#L137-158

do {
    errno = 0;

#if HAVE_NANOSLEEP
    tv.tv_sec = elapsed.tv_sec;
    tv.tv_nsec = elapsed.tv_nsec;
    was_error = nanosleep(&tv, &elapsed);
#else
    /* Calculate the time interval left (in case of interrupt) */
    now = SDL_GetTicks();
    elapsed = (now - then);
    then = now;
    if (elapsed >= ms) {
        break;
    }
    ms -= elapsed;
    tv.tv_sec = ms / 1000;
    tv.tv_usec = (ms % 1000) * 1000;

    was_error = select(0, NULL, NULL, NULL, &tv);
#endif /* HAVE_NANOSLEEP */
} while (was_error && (errno == EINTR));
like image 606
guilin 桂林 Avatar asked Jan 01 '12 08:01

guilin 桂林


Video Answer


2 Answers

This code uses select for a timeout. select usually takes a file descriptor, and makes the caller wait until an IO event occurs on the fd. It also takes a timeout argument for the maximum time to wait. Here the fd is 0, so no events will occur, and the function will always return when the timeout is reached.

The select(3) that you get from the C library is a wrapper around the select(2) system call, which means calling select(3) eventually gets you in the kernel. The kernel then doesn't schedule the process unless an IO event occurs, or the timeout is reached. So the process is not using the CPU while waiting.

Obviously, the jump into the kernel and process scheduling introduce delays. So if you must have very low latency (nanoseconds) you should use busy waiting.

like image 70
Greg Inozemtsev Avatar answered Oct 15 '22 18:10

Greg Inozemtsev


That loop won't take up all CPU. It utilizes one of two different functions to tell the operating system to pause the thread for a given amount of time and letting another thread utilize the CPU:

// First function call - if HAVE_NANOSLEEP is defined.
was_error = nanosleep(&tv, &elapsed);

// Second function call - fallback without nanosleep.
was_error = select(0, NULL, NULL, NULL, &tv);
like image 39
Anders Abel Avatar answered Oct 15 '22 20:10

Anders Abel