开发者

What is the best way to time how long functions take in C++? [duplicate]

This question already has answers here: 开发者_开发知识库 Measuring execution time of a function in C++ (14 answers) Closed 4 years ago.

In C# I would fire up the Stopwatch class to do some quick-and-dirty timing of how long certain methods take.

What is the equivalent of this in C++? Is there a high precision timer built in?


I used boost::timer for measuring the duration of an operation. It provides a very easy way to do the measurement, and at the same time being platform independent. Here is an example:

boost::timer myTimer;
doOperation();
std::cout << myTimer.elapsed();

P.S. To overcome precision errors, it would be great to measure operations that take a few seconds. Especially when you are trying to compare several alternatives. If you want to measure something that takes very little time, try putting it into a loop. For example run the operation 1000 times, and then divide the total time by 1000.


I've implemented a timer for situations like this before: I actually ended up with a class with two different implemations, one for Windows and one for POSIX.

The reason was that Windows has the QueryPerformanceCounter() function which gives you access to a very accurate clock which is ideal for such timings.

On POSIX however this isn't available so I just used boost.datetime's classes to store the start and end times then calculated the duration from those. It offers a "high resolution" timer but the resolution is undefined and varies from platform to platform.


I use my own version of Python's time_it function. The advantage of this function is that it repeats a computation as many times as necessary to obtain meaningful results. If the computation is very fast, it will be repeated many times. In the end you obtain the average time of all the repetitions. It does not use any non-standard functionality:

#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);
}

The following example uses the time_it function to measure the performance of different STL containers:

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";
    }    
}

In case anyone is curious here is the output I get (compiled with VS2008 in release mode):

vector: 8.7168

list: 27.776

deque: 91.52

set: 103.04

unordered_set: 29.76


You can use the ctime library to get the time in seconds. Getting the time in milliseconds is implementation-specific. Here is a discussion exploring some ways to do that.

See also: How to measure time in milliseconds using ANSI C?


High-precision timers are platform-specific and so aren't specified by the C++ standard, but there are libraries available. See this question for a discussion.


I humbly submit my own micro-benchmarking mini-library (on Github). It's super simple -- the only advantage it has over rolling your own is that it already has the high-performance timer code implemented for Windows and Linux, and abstracts away the annoying boilerplate.

Just pass in a function (or lambda), the number of times it should be called per test run (default: 1), and the number of test runs (default: 100). The fastest test run (measured in fractional milliseconds) is returned:

// 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;
}


#include <time.h>

clock_t start, end;
start = clock();
//Do stuff
end = clock();

printf("Took: %f\n", (float)((end - start) / (float)CLOCKS_PER_SEC));


This might be an OS-dependent issue rather than a language issue.

If you're on Windows then you can access a millisecond 10- to 16-millisecond timer through GetTickCount() or GetTickCount64(). Just call it once at the start and once at the end, and subtract.

That was what I used before if I recall correctly. The linked page has other options as well.


You can find useful this class.

Using RAII idiom, it prints the text given in construction when destructor is called, filling elapsed time placeholder with the proper value.

Example of use:

int main()
{
   trace_elapsed_time t("Elapsed time: %ts.\n");
   usleep(1.005 * 1e6);
} 

Output:

Elapsed time: 1.00509s.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜