I'm following along with day 018 (Enforcing A Video Frame Rate) using Linux. I'm using nanosleep and with the default scheduler policy SCHED_OTHER. Using this with a desired frame time of 16.67ms, frame times jump from 16ms to around 30ms basically every alternate frame, e.g. 30ms, 16ms, 31ms, 16ms, 29ms. This is under no stress at all. I assume this is something to do with the granularity of nanosleep.
I thought about setting the scheduler policy to SCHED_FIFO and setting sched_get_priority_max(SCHED_FIFO) and the nanosleep would yield the cpu to other tasks. With other processes running like xorg I thought this may cause issues for the end-user.
Therefore, I implemented a while (1) loop that just counts away the ticks, i.e. will 'melt' the CPU. Using this, I get much more consistent frame times. However, the frame time is less than what it's supposed to be, e.g. 11ms.
INTERNAL long timespec_diff(struct timespec *start, struct timespec *end) { return (BILLION * (end->tv_sec - start->tv_sec)) + (end->tv_nsec - start->tv_nsec); } int main(int argc, char *argv[]) { long desired_ns_per_frame = BILLION / 60.0f; struct timespec prev_timespec = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &prev_timespec); while (true) { // work here struct timespec end_timespec = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &end_timespec); long ns_elapsed = timespec_diff(&prev_timespec, &end_timespec); long ns_delta = desired_ns_per_frame - ns_elapsed; while (timespec_diff(&prev_timespec, &end_timespec) < ns_delta) { clock_gettime(CLOCK_MONOTONIC_RAW, &end_timespec); } } }
Can anyone explain this?
Does anyone have any suggestions/experiences with this on Linux? Thanks.