цикл while всегда занимает полную загрузку процессора? - PullRequest
6 голосов
/ 01 января 2012

Мне нужно создать игровой цикл на стороне сервера, проблема в том, как ограничить использование процессора в цикле.

По моему опыту программирования, занятый цикл всегда требует максимальной загрузки процессора. Но я читаю код SDL (Simple DirectMedia Layer), у него есть функция SDL_Delay(UINT32 ms), и у него есть цикл while. Требуется ли максимальное использование ЦП, если нет, то почему?

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));

Ответы [ 3 ]

3 голосов
/ 01 января 2012

Этот код использует select для тайм-аута.select обычно принимает файловый дескриптор и заставляет вызывающую сторону ждать, пока на fd не произойдет событие ввода-вывода.Также требуется аргумент тайм-аута для максимального времени ожидания.Здесь fd равно 0, поэтому никаких событий не произойдет, и функция всегда будет возвращаться при достижении времени ожидания.

select(3), который вы получаете из библиотеки C, является оболочкой для системы select(2)call, что означает, что вызов select(3) в конечном итоге приведет вас в ядро.Затем ядро ​​не планирует процесс, пока не произойдет событие ввода-вывода или не истечет время ожидания.Таким образом, процесс не использует процессор во время ожидания.

Очевидно, что скачок в ядре и планирование процессов приводят к задержкам.Поэтому, если у вас очень низкая задержка (наносекунды), вы должны использовать занятое ожидание.

3 голосов
/ 01 января 2012

Этот цикл не займет весь процессор. Он использует одну из двух различных функций, чтобы сообщить операционной системе приостановить поток на определенный промежуток времени и позволить другому потоку использовать процессор:

// 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);
1 голос
/ 01 января 2012

Пока поток заблокирован в SDL_Delay, он уступает ЦП другим задачам.Если задержка достаточно велика, операционная система даже переведет ЦП в режим ожидания или остановки, если не нужно выполнять никаких других действий.Обратите внимание, что это не будет хорошо работать, если время задержки не меньше 20 миллисекунд или около того.

Однако обычно это неправильный способ сделать то, что вы пытаетесь сделать.Какова ваша внешняя проблема?Почему ваш игровой цикл никогда не заканчивает делать то, что нужно сделать в это время, и поэтому нужно ждать, пока что-то произойдет, чтобы у него было больше работы?Как всегда можно выполнить бесконечное количество работы немедленно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...