0 - Delta
使用delta函数来计算时间差异:
auto start = std::chrono::steady_clock::now();
std::cout << "Elapsed(ms)=" << since(start).count() << std::endl;
since
接受任何时间点并生成任何持续时间(毫秒是默认值)。它的定义如下:
template <
class result_t = std::chrono::milliseconds,
class clock_t = std::chrono::steady_clock,
class duration_t = std::chrono::milliseconds
>
auto since(std::chrono::time_point<clock_t, duration_t> const& start)
{
return std::chrono::duration_cast<result_t>(clock_t::now() - start);
}
演示
1 - 计时器
使用基于std::chrono
的计时器:
Timer clock;
clock.tick();
clock.tock();
cout << "Run time = " << clock.duration().count() << " ms\n";
演示
计时器
的定义如下:
template <class DT = std::chrono::milliseconds,
class ClockT = std::chrono::steady_clock>
class Timer
{
using timep_t = typename ClockT::time_point;
timep_t _start = ClockT::now(), _end = {};
public:
void tick() {
_end = timep_t{};
_start = ClockT::now();
}
void tock() { _end = ClockT::now(); }
template <class T = DT>
auto duration() const {
gsl_Expects(_end != timep_t{} && "toc before reporting");
return std::chrono::duration_cast<T>(_end - _start);
}
};
正如Howard Hinnant所指出的那样,我们使用持续时间来保持在chrono
类型系统中,并执行诸如平均值或比较之类的操作(例如,在这里这意味着使用std::chrono::milliseconds
)。当我们只进行IO时,我们使用持续时间的count()
或滴答数(例如,在这里是毫秒数)。
2 - 仪器化
任何可调用对象(函数、函数对象、lambda等)都可以被仪器化以进行基准测试。假设您有一个带有参数arg1,arg2
的可调用函数F
,则此技术的结果为:
cout << "F runtime=" << measure<>::duration(F, arg1, arg2).count() << "ms";
演示
measure
的定义如下:
template <class TimeT = std::chrono::milliseconds,
class ClockT = std::chrono::steady_clock>
struct measure
{
template<class F, class ...Args>
static auto duration(F&& func, Args&&... args)
{
auto start = ClockT::now();
std::invoke(std::forward<F>(func), std::forward<Args>(args)...);
return std::chrono::duration_cast<TimeT>(ClockT::now()-start);
}
};
如(1)所述,使用不带
.count()
的持续时间对于那些想要在I/O之前进行一堆持续时间的后处理的客户端最为有用,例如平均值:
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2;
std::cout << "Average run time " << avg.count() << " ms\n";
+这就是为什么要转发函数调用。
+完整代码可以在这里找到。
+我尝试基于chrono构建一个基准测试框架的记录可以在这里找到。
+旧版演示
time()
会返回一个不同的值。 - Thomastime(NULL)
获取当前时间(自1970年1月1日以来的秒数)...第二次调用它将在第一次之后N秒,因此...不同(除非你所做的事情不需要一秒钟完成...在这种情况下,它将与第一个相同)。 - Brian Roach