0

I have a large codebase and I want to manually add some timers to profile some sections of the code. Some of those sections are within a loop, so I would like to aggregate all the wall time spent there for each iteration.

What I'd like to do in a Pythonic pseudo-code:

time_step_1 = 0
time_step_2 = 0
for pair in pairs:

    start_step_1 = time.now()
    run_step_1(pair)
    time_step_1 += start_step_1 - time.now()

    start_step_2 = time.now()
    run_step_2(pair)
    time_step_2 += start_step_2 - time.now()

print("Time spent in step 1", time_step_1)
print("Time spent in step 2", time_step_2)

Is there a library in C++ to do this? Otherwise would you recommend using boost::timer, create a map of timers and then resume and stop at each iteration?

Andrea Zonca
  • 8,378
  • 9
  • 42
  • 70
  • 1
    You may want to take a look at `std::chrono` library http://en.cppreference.com/w/cpp/header/chrono – Emerald Weapon Mar 21 '18 at 23:01
  • Depending on just how much code you want to measure, I would consider using a couple of RAII Classes, one to keep the overall time records and print the summary at the end, and the other to record the individual time for a step, where it's constructor records time.now() and it's destructor some the calculation and adds the duration to the overall tally. With such a system you can have minimal extra code to do the measuring and printing as well as allowing you to calculate average times for steps, how many times they run etc. – Ian4264 Mar 21 '18 at 23:30
  • Look into the `ctime` and `chrono` libraries. – eesiraed Mar 22 '18 at 00:14
  • thanks, isn't this a common situation? isn't there already a full fledged library that can handle this without writing my own? – Andrea Zonca Mar 22 '18 at 09:23

1 Answers1

1

Not very advanced, but for basic time measurement, you can use std::chrono library, specifically the std::chrono::high_resolution_clock - the clock with smallest tick period (= highest accuracy) provided by the implementation.

For some more trivial time measurement, I have used RAII classes similar to this:

#include <chrono>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>

class TimeMeasureGuard {
public:
    using clock_type = std::chrono::high_resolution_clock;

private:
    const std::string m_testName;
    std::ostream& m_os;

    clock_type::time_point started_at;
    clock_type::time_point ended_at;

public:
    TimeMeasureGuard(const std::string& testName, std::ostream& os = std::cerr)
        : m_testName(testName), m_os(os)
    {
        started_at = clock_type::now();
    }

    ~TimeMeasureGuard()
    {
        ended_at = clock_type::now();

        // Get duration
        const auto duration = ended_at - started_at;

        // Get duration in nanoseconds
        const auto durationNs = std::chrono::nanoseconds(duration).count();
        // ...or in microseconds:
        const auto durationUs
            = std::chrono::duration_cast<std::chrono::microseconds>(duration).count();

        // Report total run time into 'm_os' stream
        m_os << "[Test " << std::quoted(m_testName) << "]: Total run time: "
             << durationNs << " ns, " << "or: " << durationUs << " us" << std::endl;
    }
};

Of course this is a very simple class, which would deserve several improvements before being used for a real measurement.

You can use this class like:

std::uint64_t computeSquares()
{
    std::uint64_t interestingNumbers = 0;
    {
        auto time_measurement = TimeMeasureGuard("Test1");

        for (std::uint64_t x = 0; x < 1'000; ++x) {
            for (std::uint64_t y = 0; y < 1'000; ++y) {
                if ((x * y) % 42 == 0)
                    ++interestingNumbers;
            }
        }
    }
    return interestingNumbers;
}

int main()
{
    std::cout << "Computing all x * y, where 'x' and 'y' are from 1 to 1'000..."
              << std::endl;
    const auto res = computeSquares();
    std::cerr << "Interesting numbers found: " << res << std::endl;

    return 0;
}

And the output is:

Computing all x * y, where 'x' and 'y' are from 1 to 1'000...
[Test "Test1"]: Total run time: 6311371 ns, or: 6311 us
Interesting numbers found: 111170

For simple time measurement cases, this might be easier than using a whole timer library, and it's just a few lines of code, you don't need to include lots of headers.

Miroslav Mares
  • 2,292
  • 3
  • 22
  • 27
  • thanks! this is very useful, what if the guard is **inside** a loop, would it add up each run? also, let's say I want a whole timer library, which one do you recommend? – Andrea Zonca Mar 22 '18 at 09:25
  • @AndreaZonca If the RAII guard is **inside** a loop, it gets created and destroyed each loop iteration. So the result is "a lots of measurements of single loop iteration". To answer your question about the timer library, I unfortunately cannot tell as I only used `std::chrono`. But I would not hesitate to try `boost::timer`, as Boost libraries are usually very high quality. – Miroslav Mares Mar 22 '18 at 16:47