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

时间:2019-02-12 23:35:07

标签: c++ c++11 timer

使用std::this_thread::sleep_for()毫秒以上时是否存在任何已知的可移植性问题?

在我正在从事的项目中,我希望使用从Microsoft的Sleep()到{{ 1}}到naonsleep(),具体取决于特定平台上的可用内容。其中一些具有明显的局限性,例如在某些平台上不支持1000 ms或更长的延迟。

usleep也受这种怪癖困扰吗?

2 个答案:

答案 0 :(得分:2)

最长睡眠时间:std::this_thread::sleep_for()在这里没有任何问题。您可以随意睡觉。

精度:std::this_thread::sleep_for()与您提到的所有其他睡眠功能也存在相同的问题:可能不是!请参见下面的更新!

当实际恢复任务时,任何睡眠功能都会遭受quirk的困扰,这完全取决于操作系统中的调度程序。通常,您的睡眠时间会在抢先式多任务调度程序的最短时间范围内出现混淆。

更糟糕的是,这个时间片在所有操作系统上并不总是恒定的。

在Linux上,您通常有10 ms的时间片,并且睡眠时间少于10 ms 可能导致睡眠时间为0 ms。睡眠10毫秒可能导致大约睡眠10毫秒或更长时间,可能但不一定与时间片大小对齐。

简而言之:您完全不能依赖任何睡眠功能,包括std::this_thread::sleep_for()

还有另一种睡眠功能,可以忙于等待。通常在等待时间明显短于调度时间片(例如2 us)的时间中使用。但是当然,这甚至可能是非常不准确的,因为即使在几乎闲置的系统上,您的任务也可能被抢占,然后您可以将10 us加到2 us睡眠时间。

在多任务操作系统上,您没有机会:您无法精确入睡。睡眠功能有错误,甚至有系统的错误,因此实际上睡眠100次10 ms可能会睡0到2秒之间的任何时间。

如果您有长期的时间要求,唯一的机会就是不断查询挂钟时间。

更新:Linux和macOS上的基准:

至少在Linux和macOS std::this_thread::sleep_for()上,毫秒精度非常精确,因此不会会遭受我上面描述的所有干扰:

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

与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

两次运行均在空闲系统上。有趣的是:在Linux上,数字在加载的系统上更加精确(在屏幕会话中为是)。调度程序工件!但是小的! :-)

这是针对Linux上的usleep():也相当精确。我不再相信我在上面写的内容:

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

答案 1 :(得分:0)

sleep_for支持更长的延迟,因为它接受任何有效的持续时间值。但是,它确实有局限性:

sleep_for通常使用std::chrono::steady_clock,因此受该时钟的限制。该标准要求时钟单调前进。但是解决方案可能因实施而异。

也是

  

由于调度或资源争用延迟,此功能可能阻塞的时间比sleep_duration长。 sleep_for (cpp reference)

所以sleep_for的睡眠时间可能比指定时间长。

相关问题