我为我的目的做了类似的事情,不过只针对 Linux。你可以在这里找到代码;随意以任何你想要的方式使用代码。
我的实施解决的挑战与您的问题中提到的挑战部分重叠。具体来说:
刻度因子(需要从时钟刻度转换为基于秒的时间单位)在运行时检索,但仅使用第now()
一次‡。如果您担心这会导致较小的开销,您可以now()
在启动时调用该函数一次,然后再测量任何实际间隔。刻度因子存储在静态变量中,这意味着仍然存在一些开销,因为在最低级别上,now()
函数的每次调用都意味着检查静态变量是否已被初始化。然而,这个开销在每次调用中都是相同的now()
,所以它不应该影响测量时间间隔。
默认情况下我不转换为纳秒,因为当测量相对较长的时间段(例如几秒)时,这会导致溢出非常快。这实际上是我不使用 boost 实现的主要原因。我没有转换为纳秒,而是将基本单位实现为模板参数(Precision
在代码中调用)。我使用std::ratio
C++11 作为模板参数。所以我可以选择,例如 a clock<micro>
,这意味着调用该now()
函数将在内部转换为微秒而不是纳秒,这意味着我可以测量许多秒或数分钟的周期而不会溢出并且仍然具有良好的精度。(这与用于产生输出的单位无关。您可以有一个clock<micro>
并以秒为单位显示结果等)
我的时钟类型,称为combined_clock
结合了用户时间、系统时间和挂钟时间。这也有一个升压时钟类型,但它与来自的比率类型和单位不兼容std
,而我的是。
‡刻度因子是使用::sysconf()
您建议的调用检索的,并且保证在整个过程的生命周期内返回一个相同的值。
所以你使用它的方式如下:
#include "util/proctime.hpp"
#include <ratio>
#include <chrono>
#include <thread>
#include <utility>
#include <iostream>
int main()
{
using std::chrono::duration_cast;
using millisec = std::chrono::milliseconds;
using clock_type = rlxutil::combined_clock<std::micro>;
auto tp1 = clock_type::now();
/* Perform some random calculations. */
unsigned long step1 = 1;
unsigned long step2 = 1;
for (int i = 0 ; i < 50000000 ; ++i) {
unsigned long step3 = step1 + step2;
std::swap(step1,step2);
std::swap(step2,step3);
}
/* Sleep for a while (this adds to real time, but not CPU time). */
std::this_thread::sleep_for(millisec(1000));
auto tp2 = clock_type::now();
std::cout << "Elapsed time: "
<< duration_cast<millisec>(tp2 - tp1)
<< std::endl;
return 0;
}
上面的用法涉及一个漂亮的打印函数,它生成如下输出:
Elapsed time: [user 40, system 0, real 1070 millisec]