简体   繁体   English

对于`std :: this_thread :: sleep_for()`有任何特定于平台的限制吗?

[英]Are there any platform-specific limitations to `std::this_thread::sleep_for()`?

Are there any known portability issues to consider when using std::this_thread::sleep_for() for milliseconds and upward? 在使用std::this_thread::sleep_for()毫秒和向上时,是否有任何已知的可移植性问题需要考虑?

In a project I'm working on, I hope to replace a bouquet of platform-specific implementations all designed to yield for a specified number of milliseconds, give or take, using anything from Microsoft's Sleep() to naonsleep() to usleep , depending on what is available on a particular platform. 在我正在开发的一个项目中,我希望能够替换一系列特定于平台的实现,这些实现都是为了产生指定的毫秒数而提供或者使用,使用从Microsoft的Sleep()naonsleep()usleep任何东西,具体取决于在特定平台上可用的内容。 Some of these come with notable limitations, such as not supporting delays of 1000 ms or more on certain platforms. 其中一些具有明显的局限性,例如在某些平台上不支持1000毫秒或更长的延迟。

Does std::this_thread::sleep_for() suffer from such quirks, too? std::this_thread::sleep_for()遭受这样的怪癖吗?

Maximum sleep duration: std::this_thread::sleep_for() does not have any problem here. 最大睡眠持续时间: std::this_thread::sleep_for()在这里没有任何问题。 You can sleep as long as you like. 只要你愿意,你就可以睡觉。

Precision: std::this_thread::sleep_for() has the same problems which all the other sleep functions you mention also have: Probably not! 精度: std::this_thread::sleep_for()有同样的问题,你提到的所有其他睡眠功能也有: 可能不是! See update below! 见下面的更新!

Any sleep function will suffer the quirk that it is entirely up to the scheduler in your operating system when your task is actually resumed. 当您的任务实际恢复时,任何睡眠功能都会受到这样的quirk ,即它完全取决于操作系统中的调度程序。 Your sleep times will generally alias somewhat around the minimum time slice of your preemptive multitasking scheduler. 您的睡眠时间通常会在抢占式多任务调度程序的最小时间片周围有所不同。

To make things worse, this time slice is not always constant on all OSes. 更糟糕的是,这个时间片在所有操作系统上并不总是不变的。

On Linux you usually have 10 ms time slices and sleeping less than 10 ms may result in sleeping 0 ms. 在Linux上,您通常有10毫秒的时间片,睡眠时间小于10毫秒可能导致睡眠时间为0毫秒。 Sleeping for 10 ms may result in sleeping for about 10 ms, or longer, potentially but not necessarily aligned to a time slice size. 睡眠10毫秒可能导致睡眠 10毫秒或更长时间,可能但不一定与时间片大小对齐。

In short: You cannot rely at all on any of the sleep functions, including std::this_thread::sleep_for() . 简而言之:您根本无法依赖任何睡眠函数,包括std::this_thread::sleep_for()

There is another class of sleep functions which does busy waiting. 还有另一类睡眠功能,可以忙着等待。 This is usually used when waiting for times which are significantly shorter than a scheduling time slice (say 2 us). 这通常在等待明显短于调度时间片(例如2 us)的时间时使用。 But of course even this may be very inaccurate since your task may get preempted even on an almost idle system, and then you can add 10 ms to your 2 us sleep time. 但是,当然即使这可能是非常不准确的,因为即使在几乎空闲的系统上你的任务也可能被抢占,然后你可以为你的2 us睡眠时间增加10 ms。

On a multitasking operating system you have no chance: You cannot sleep precisely. 在多任务操作系统上,您没有机会:您无法准确入睡。 The sleep functions have errors, and they even have systematic errors, so sleeping 100 times 10 ms may sleep anything between 0 and 2 seconds in practice. 睡眠功能有错误,甚至有系统错误,因此睡眠100次10毫秒可能会在0到2秒之间睡眠。

If you have long-term time requirements the only chance you have is to constantly query the wall-clock time. 如果您有长期时间要求,您唯一的机会就是不断查询挂钟时间。

Update: Benchmarks on Linux and macOS: 更新:Linux和macOS的基准测试:

At least on Linux and macOS std::this_thread::sleep_for() are pretty precise for millisecond resolution and so not suffer from all the artifacts I described above: 至少在Linux和macOS上, std::this_thread::sleep_for()对于毫秒分辨率非常精确,因此不会受到我上面描述的所有工件的影响:

Linux benchmark: Each sleep is called repeatedly for a total duration of one second and the real average sleep time is given (eg averaging over 200 calls to sleep(5 ms)): Linux基准测试:每次睡眠被重复调用,持续时间为一秒,并给出实际平均睡眠时间(例如,平均超过200次睡眠呼叫(5毫秒)):

std::this_thread::sleep( 1 ms) slept really 1.13915 ms
std::this_thread::sleep( 2 ms) slept really 2.15215 ms
std::this_thread::sleep( 3 ms) slept really 3.14976 ms
std::this_thread::sleep( 4 ms) slept really 4.15059 ms
std::this_thread::sleep( 5 ms) slept really 5.15062 ms
std::this_thread::sleep( 6 ms) slept really 6.15008 ms
std::this_thread::sleep( 7 ms) slept really 7.14988 ms
std::this_thread::sleep( 8 ms) slept really 8.14979 ms
std::this_thread::sleep( 9 ms) slept really 9.15044 ms
std::this_thread::sleep(10 ms) slept really 10.1504 ms
std::this_thread::sleep(11 ms) slept really 11.1511 ms
std::this_thread::sleep(12 ms) slept really 12.1505 ms
std::this_thread::sleep(13 ms) slept really 13.1504 ms
std::this_thread::sleep(14 ms) slept really 14.1501 ms
std::this_thread::sleep(15 ms) slept really 15.1503 ms
std::this_thread::sleep(16 ms) slept really 16.1499 ms
std::this_thread::sleep(17 ms) slept really 17.1505 ms
std::this_thread::sleep(18 ms) slept really 18.1505 ms
std::this_thread::sleep(19 ms) slept really 19.1504 ms
std::this_thread::sleep(20 ms) slept really 20.1505 ms

Same for macOS: 对于macOS也是如此:

std::this_thread::sleep( 1 ms) slept really 1.27451 ms
std::this_thread::sleep( 2 ms) slept really 2.45646 ms
std::this_thread::sleep( 3 ms) slept really 3.61991 ms
std::this_thread::sleep( 4 ms) slept really 4.77443 ms
std::this_thread::sleep( 5 ms) slept really 5.7994 ms
std::this_thread::sleep( 6 ms) slept really 7.03769 ms
std::this_thread::sleep( 7 ms) slept really 8.13089 ms
std::this_thread::sleep( 8 ms) slept really 9.13276 ms
std::this_thread::sleep( 9 ms) slept really 10.441 ms
std::this_thread::sleep(10 ms) slept really 11.5895 ms
std::this_thread::sleep(11 ms) slept really 12.77 ms
std::this_thread::sleep(12 ms) slept really 13.8207 ms
std::this_thread::sleep(13 ms) slept really 14.9366 ms
std::this_thread::sleep(14 ms) slept really 16.4569 ms
std::this_thread::sleep(15 ms) slept really 17.27 ms
std::this_thread::sleep(16 ms) slept really 18.2013 ms
std::this_thread::sleep(17 ms) slept really 19.6347 ms
std::this_thread::sleep(18 ms) slept really 20.7785 ms
std::this_thread::sleep(19 ms) slept really 22.9571 ms
std::this_thread::sleep(20 ms) slept really 23.2532 ms

Both runs are on an idle system. 两次运行都在空闲系统上。 Interesting: On Linux the numbers get more precise on a loaded system (yes in a screen session). 有趣的是:在Linux上,数字在加载的系统上变得更加精确(在屏幕会话中是的)。 Scheduler artifacts! 调度器工件! But small ones! 但小的! :-) :-)

This is for usleep() on Linux: Also pretty precise. 这适用于Linux上的usleep() :也非常精确。 I no longer believe what I wrote above: 我不再相信我上面写的内容:

usleep( 1 ms) slept really  1.148 ms
usleep( 2 ms) slept really  2.152 ms
usleep( 3 ms) slept really  3.151 ms
usleep( 4 ms) slept really  4.151 ms
usleep( 5 ms) slept really  5.149 ms
usleep( 6 ms) slept really  6.149 ms
usleep( 7 ms) slept really  7.149 ms
usleep( 8 ms) slept really  8.150 ms
usleep( 9 ms) slept really  9.150 ms
usleep(10 ms) slept really 10.150 ms
usleep(11 ms) slept really 11.149 ms
usleep(12 ms) slept really 12.149 ms
usleep(13 ms) slept really 13.150 ms
usleep(14 ms) slept really 14.150 ms
usleep(15 ms) slept really 15.149 ms
usleep(16 ms) slept really 16.149 ms
usleep(17 ms) slept really 17.150 ms
usleep(18 ms) slept really 18.150 ms
usleep(19 ms) slept really 19.149 ms
usleep(20 ms) slept really 20.149 ms

sleep_for supports longer delays, as it accepts any valid duration value. sleep_for支持更长的延迟,因为它接受任何有效的持续时间值。 However, it does have limitations: 但是,它确实有局限性:

sleep_for generally uses std::chrono::steady_clock , and is thus subject to the limitations of that clock. sleep_for通常使用std::chrono::steady_clock ,因此受到该时钟的限制。 The standard requires that clock to monotonically advance. 该标准要求时钟单调前进。 But the resolution may vary from implementation to implementation. 但决议可能因实施而异。

Also, 也,

This function may block for longer than sleep_duration due to scheduling or resource contention delays. 由于调度或资源争用延迟,此功能可能会阻塞比sleep_duration更长的时间。 sleep_for (cpp reference) sleep_for(cpp参考)

So sleep_for may sleep for longer than specified. 所以sleep_for可能会睡眠时间超过指定时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM