如果我并排放两个电话来确定最小的可测量持续时间:
// g++ -std=c++11 -O3 -Wall test.cpp
#include <chrono>
typedef std::chrono::high_resolution_clock hrc;
hrc::time_point start = hrc::now();
hrc::time_point end = hrc::now();
std::chrono::nanoseconds duration = end - start;
std::cout << "duration: " << duration.count() << " ns" << std::endl;
我已经在循环中运行了数千次,并且在我特定的3.40GHz桌面上我一直得到40 ns +/- 2 ns。
但是,当我想看看我能睡到的最短时间时:
#include <thread>
hrc::time_point start = hrc::now();
std::this_thread::sleep_for( std::chrono::nanoseconds(1) );
hrc::time_point end = hrc::now();
std::chrono::nanoseconds duration = end - start;
std::cout << "slept for: " << duration.count() << " ns" << std::endl;
这告诉我,我平均睡眠55400纳秒,或55.4微秒。远远超过我的预期。
把上面的代码放到for()
循环中,我试着睡不同的数量,这就是结果:
我有一些问题:
有什么可以解释这些数字?
有一个非常明显的模式,你的所有结果都比你要求睡觉的时间长54000ns。如果你看看GCC的this_thread::sleep_for()
是如何在GNU / Linux上实现的,你会看到它只使用nanospleep
,正如Cubbi的评论所说,调用该函数可能需要大约50000ns。我猜一些成本就是进行系统调用,因此从用户空间切换到内核并返回。
为什么在负时间内睡眠会返回200+ ns,而睡眠时间为0+纳秒会导致50,000+纳秒?
猜测我会说C库会检查负数并且不会进行系统调用。
负数作为睡眠时间是记录/支持的功能,还是我不小心偶然发现了一些我不能依赖的奇怪错误?
标准不禁止传递否定参数,因此允许它,并且函数应该“立即”返回,因为相对超时指定的时间已经过去了。你不能依赖负参数返回比非负参数更快,这是你特定实现的一个人工制品。
是否有更好的C ++睡眠调用可以让我更加一致/可预测的睡眠时间?
我不这么认为 - 如果我知道一个,那么我们将在GCC中使用它来实现this_thread::sleep_for()
。
编辑:在更新版本的GCC的libstdc ++中我添加了:
if (__rtime <= __rtime.zero())
return;
因此,当请求零或负持续时间时,将不会有系统调用。
在struct task_struct中的内核init / init_task.c中定义了init_task的param
.timer_slack_ns = 50000, /* 50 usec default slack */
它添加到hrtimer_nanosleep()内核函数中的非RT进程中,以减少计时器的hardirqs次数。