在准确,精确的间隔上定期执行功能
我想为我的应用程序实现准确,精确的倒计时计时器。我从最简单的实现开始,这根本不准确。
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了确切的时机,您基本上必须忙于等待:
time.elapsed()<间隔{}
。这也称为“旋转”(您可能已经听说过“旋转锁”)。当然,这比使用OS提供的睡眠功能(通常以某种低功率模式过渡CPU)要大得多。要稍微改善这一点,您可以在循环主体中绝对什么都不做,而是可以:
thread :: fard_now()
。std :: hint :: hint /code>
不幸的是,我真的不能告诉您这两个功能为您提供了什么时间。但是从文档看来,
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:
thread::yield_now()
.std::hint::spin_loop()
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.