在 C# 中,我会启动 Stopwatch 类来快速确定某些方法需要多长时间。
这在 C++ 中的等价物是什么?有内置高精度定时器吗?
我使用boost::timer来测量操作的持续时间。它提供了一种非常简单的测量方法,同时独立于平台。这是一个例子:
boost::timer myTimer;
doOperation();
std::cout << myTimer.elapsed();
PS为了克服精度误差,测量需要几秒钟的操作会很棒。特别是当您尝试比较几种替代方案时。如果您想测量花费很少时间的东西,请尝试将其放入循环中。例如运行操作 1000 次,然后将总时间除以 1000。
我之前已经为这样的情况实现了一个计时器:我实际上最终得到了一个具有两种不同实现的类,一个用于 Windows,一个用于 POSIX。
原因是 Windows 具有QueryPerformanceCounter()
让您访问非常准确的时钟的功能,该时钟非常适合此类计时。
但是在 POSIX 上这是不可用的,所以我只是使用boost.datetime的类来存储开始和结束时间,然后从中计算持续时间。它提供了一个“高分辨率”计时器,但分辨率未定义,并且因平台而异。
我使用我自己版本的 Pythontime_it
函数。此函数的优点是它可以根据需要重复计算多次以获得有意义的结果。如果计算速度很快,就会重复很多次。最后,您获得所有重复的平均时间。它不使用任何非标准功能:
#include <ctime>
double clock_diff_to_sec(long clock_diff)
{
return double(clock_diff) / CLOCKS_PER_SEC;
}
template<class Proc>
double time_it(Proc proc, int N=1) // returns time in microseconds
{
std::clock_t const start = std::clock();
for(int i = 0; i < N; ++i)
proc();
std::clock_t const end = std::clock();
if(clock_diff_to_sec(end - start) < .2)
return time_it(proc, N * 5);
return clock_diff_to_sec(end - start) * (1e6 / N);
}
以下示例使用该time_it
函数来衡量不同 STL 容器的性能:
void dummy_op(int i)
{
if(i == -1)
std::cout << i << "\n";
}
template<class Container>
void test(Container const & c)
{
std::for_each(c.begin(), c.end(), &dummy_op);
}
template<class OutIt>
void init(OutIt it)
{
for(int i = 0; i < 1000; ++i)
*it = i;
}
int main( int argc, char ** argv )
{
{
std::vector<int> c;
init(std::back_inserter(c));
std::cout << "vector: "
<< time_it(boost::bind(&test<std::vector<int> >, c)) << "\n";
}
{
std::list<int> c;
init(std::back_inserter(c));
std::cout << "list: "
<< time_it(boost::bind(&test<std::list<int> >, c)) << "\n";
}
{
std::deque<int> c;
init(std::back_inserter(c));
std::cout << "deque: "
<< time_it(boost::bind(&test<std::deque<int> >, c)) << "\n";
}
{
std::set<int> c;
init(std::inserter(c, c.begin()));
std::cout << "set: "
<< time_it(boost::bind(&test<std::set<int> >, c)) << "\n";
}
{
std::tr1::unordered_set<int> c;
init(std::inserter(c, c.begin()));
std::cout << "unordered_set: "
<< time_it(boost::bind(&test<std::tr1::unordered_set<int> >, c)) << "\n";
}
}
如果有人好奇,这里是我得到的输出(在发布模式下使用 VS2008 编译):
矢量:8.7168
清单:27.776
双端队列:91.52
套装:103.04
无序集:29.76
高精度计时器是特定于平台的,因此 C++ 标准没有指定,但有可用的库。请参阅此问题进行讨论。
我谦虚地提交了我自己的微基准测试迷你库(在 Github 上)。它超级简单——它比自己滚动的唯一优势是它已经为 Windows 和 Linux 实现了高性能计时器代码,并抽象出烦人的样板。
只需传入一个函数(或 lambda)、每次测试运行应调用的次数(默认值:1)和测试运行次数(默认值:100)。返回最快的测试运行(以毫秒为单位测量):
// Example that times the compare-and-swap atomic operation from C++11
// Sample GCC command: g++ -std=c++11 -DNDEBUG -O3 -lrt main.cpp microbench/systemtime.cpp -o bench
#include "microbench/microbench.h"
#include <cstdio>
#include <atomic>
int main()
{
std::atomic<int> x(0);
int y = 0;
printf("CAS takes %.4fms to execute 100000 iterations\n",
moodycamel::microbench(
[&]() { x.compare_exchange_strong(y, 0); }, /* function to benchmark */
100000, /* iterations per test run */
100 /* test runs */
)
);
// Result: Clocks in at 1.2ms (12ns per CAS operation) in my environment
return 0;
}
你可以找到有用的这个类。
使用 RAII 习语,它在调用析构函数时打印构造中给出的文本,并用适当的值填充经过的时间占位符。
使用示例:
int main()
{
trace_elapsed_time t("Elapsed time: %ts.\n");
usleep(1.005 * 1e6);
}
输出:
Elapsed time: 1.00509s.
这可能是依赖于操作系统的问题,而不是语言问题。
如果您使用的是 Windows,则可以通过GetTickCount()或 GetTickCount64()访问 10 到 16 毫秒的毫秒计时器。只需在开始和结束时调用一次,然后减去。
如果我没记错的话,那是我以前用过的。链接页面还有其他选项。
#include <time.h>
clock_t start, end;
start = clock();
//Do stuff
end = clock();
printf("Took: %f\n", (float)((end - start) / (float)CLOCKS_PER_SEC));