在准确,精确的间隔上定期执行功能

发布于 2025-02-12 18:30:34 字数 760 浏览 2 评论 0原文

我想为我的应用程序实现准确,精确的倒计时计时器。我从最简单的实现开始,这根本不准确。

loop {
    // Code which can take upto 10 ms to finish
    ...

    let interval = std::time::Duration::from_millis(1000);
    std::thread::sleep(interval);
}

由于睡眠通话之前的代码可能需要一些时间才能完成,因此我无法以预期的间隔运行下一个迭代。更糟糕的是,如果倒计时计时器运行2分钟,则每次迭代的10毫秒总计总计1.2秒。因此,此版本不是很准确。

我可以通过衡量该代码执行时间花费多少时间来解释这一延迟。

loop {
    let start = std::time::Instant::now();

    // Code which can take upto 10 ms to finish
    ...

    let interval = std::time::Duration::from_millis(1000);
    std::thread::sleep(interval - start.elapsed());
}

即使这似乎很精确,直到毫秒到毫秒,我还是想知道是否有一种实现此功能的方法,它更准确,更精确,并且通常在软件中如何完成。

I want to implement an accurate and precise countdown timer for my application. I started with the most simple implementation, which was not accurate at all.

loop {
    // Code which can take upto 10 ms to finish
    ...

    let interval = std::time::Duration::from_millis(1000);
    std::thread::sleep(interval);
}

As the code before the sleep call can take some time to finish, I cannot run the next iteration at the intended interval. Even worse, if the countdown timer is run for 2 minutes, the 10 milliseconds from each iteration add up to 1.2 seconds. So, this version is not very accurate.

I can account for this delay by measuring how much time this code takes to execute.

loop {
    let start = std::time::Instant::now();

    // Code which can take upto 10 ms to finish
    ...

    let interval = std::time::Duration::from_millis(1000);
    std::thread::sleep(interval - start.elapsed());
}

Even though this seems to precise up to milliseconds, I wanted to know if there is a way to implement this which is even more accurate and precise and/or how it is usually done in software.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温馨耳语 2025-02-19 18:30:34

为了确切的时机,您基本上必须忙于等待:time.elapsed()<间隔{}。这也称为“旋转”(您可能已经听说过“旋转锁”)。当然,这比使用OS提供的睡眠功能(通常以某种低功率模式过渡CPU)要大得多。

要稍微改善这一点,您可以在循环主体中绝对什么都不做,而是可以:

不幸的是,我真的不能告诉您这两个功能为您提供了什么时间。但是从文档看来,spin_loop将导致更精确的时机。

另外,您很可能希望将“旋转等待”与std :: thread :: Sleep相结合,以便大部分时间都使用后一种方法睡觉。这样可以节省大量的功率/CPU资源。嘿,甚至还有一个板条箱: spin_sleep 。您可能应该只使用它。

最后,以防万一您不知道:对于这些“时间”的几种用例,您可以使用其他功能。例如,如果您想每60秒渲染一个框架,则需要使用一些API,可以直接与监视器的刷新速率/v-Blanking同步,而不是手动睡觉。

For precise timing, you basically have to busy wait: while time.elapsed() < interval {}. This is also called "spinning" (you might have heard of "spin lock"). Of course, this is far more CPU intensive than using the OS-provided sleep functionality (which often transitions the CPU in some low power mode).

To improve upon that slightly, instead of doing absolutely nothing in the loop body, you could:

Unfortunately, I can't really tell you what timing guarantees these two functions give you. But from the documentation it seems like spin_loop will result in more precise timing.

Also, you very likely want to combine the "spin waiting" with std::thread::sleep so that you sleep the majority of the time with the latter method. That saves a lot of power/CPU-resources. And hey, there is even a crate for exactly that: spin_sleep. You should probably just use that.

Finally, just in case you are not aware: for several use cases of these "timings", there are other functions you can use. For example, if you want to render a frame every 60th of a second, you want to use some API that synchronizes your loop with the refresh rate/v-blanking of the monitor directly, instead of manually sleeping.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文