rustframe-ratethread-sleepgame-loop

Rust lang thread::sleep() sleeping for almost twice the specified time during game loop on windows


So I've written the following function to show what i mean:

use std::{thread, time};

const TARGET_FPS: u64 = 60;

fn main() {
    let mut frames = 0;
    let target_ft = time::Duration::from_micros(1000000 / TARGET_FPS);
    println!("target frame time: {:?}",target_ft);
    let mut time_slept = time::Duration::from_micros(0);
    let start = time::Instant::now();
    loop {
        let frame_time = time::Instant::now();

        frames+=1;
        if frames == 60 {
            break
        }

        if let Some(i) = (target_ft).checked_sub(frame_time.elapsed()) {
            time_slept+=i;
            thread::sleep(i)
        }
    }
    println!("time elapsed: {:?}",start.elapsed());
    println!("time slept: {:?}",time_slept);
}

The idea of the function is to execute 60 cycles at 60fps then exit with the time elapsed and the total time spent sleeping during the loop. ideally, since im executing 60 cycles at 60fps with no real calculations happening between, it should take about one second to execute and spend basically the entire second sleeping. but instead when i run it it returns:

target frame time: 16.666ms
time elapsed: 1.8262798s
time slept: 983.2533ms

As you can see, even though it was only told to sleep for a total of 983ms, the 60 cycles took nearly 2 seconds to complete. Because of this nearly 50% inaccuracy, a loop told to run at 60fps instead runs at only 34fps.

The docs say The thread may sleep longer than the duration specified due to scheduling specifics or platform-dependent functionality. It will never sleep less. But is this really just from that? Am i doing something wrong?


Solution

  • i switched to using spin_sleep::sleep(i) from https://crates.io/crates/spin_sleep and it seems to have fixed it. i guess it must just be windows inaccuracies then...still strange that time::sleep on windows would be that far off for something as simple as a game loop