2
\$\begingroup\$

I need to time a few functions that I'm implementing, so I decided to implement a way of timing even multiple or sub calls based on the stack data structure and on the tic and toc commands of Matlab.

tictoc.h

#include <assert.h>
#include <cmath>
#include <ctime>
#include <iostream>
#include <stack>

static std::stack<std::clock_t> starting_times;

void start_timer()
{
    starting_times.push(std::clock());
}

int stop_timer(bool print, const char* to_execute = "")
{

    assert(!starting_times.empty());

    double milliseconds = (std::clock() - starting_times.top()) / (double)(CLOCKS_PER_SEC / 1000);
    starting_times.pop();

    if (print) {

        // minutes
        if (milliseconds >= 60 * 1000) {

            double m = milliseconds / 1000 / 60;
            double s = std::fmod(m, 60);
            double ms = std::fmod(s, 1000);

            std::cout << "Time elapsed '"
                      << std::lrint(m) << "m, "
                      << std::lrint(s) << "s and "
                      << std::lrint(ms) << "ms' "
                      << to_execute << "\n";

        } else if (milliseconds >= 1000) {
            std::cout << "Time elapsed '"
                      << std::lrint(milliseconds / 1000) << "s and "
                      << std::lrint(std::fmod(milliseconds, 1000)) << "ms' "
                      << to_execute << "\n";
        } else {
            std::cout << "Time elapsed '" << milliseconds << "ms' " << to_execute << "\n";
        }
    }

    return milliseconds;
}

to_execute is just a string that is eventually passed to describe which functions has just stopped being executed.

Of course, as you can observe from this code, I'm not expecting the functions to last more than 60 minutes, but if you think it's a good idea to add it, feel free to suggest a way to do it.

Of course, I've already tried the code and it seems to work.

Here's a simple runnable example that could use these functions:

main.cpp

#include "tictoc.h"
#include <iostream>

int main(const int argc, const char** argv)
{

    start_timer();

    int sum = 0;
    for (int i = 0; i < 10000; ++i) {
        sum += i;
    }

    std::cout << "sum = " << sum << "\n";

    stop_timer(true, "to execute the sum from 0 to 999");

    return 0;
}

Now put this and tictoc.h above in the same folder and compile with C++11, assuming you have it:

g++ -std=c++11 main.cpp -o main

Run executable main as:

./main
\$\endgroup\$
1
\$\begingroup\$

So as you are using c++ you should use the stl for that

#include <chrono>
#include <iostream>
int main() {
    std::chrono::high_resolution_clock::time_point start, end;

    start = std::chrono::high_resolution_clock::now();    
    /* do someting */
    end = std::chrono::high_resolution_clock::now();
    double time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( end - start ).count();
    std::cout << "Code took " << time_elapsed << " miliseconds to execute\n";
};

EDIT

So here an more extended version

#include <chrono>
#include <iostream>

std::chrono::high_resolution_clock::time_point start_timer() {
    return std::chrono::high_resolution_clock::now();
}

void stop_timer (clock::time_point &start, std::string &message) {
    using cast = std::chrono::duration_cast;
    auto duration = cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
    auto hours    = cast<std::chrono::hours>(duration).count();
    duration     -= cast<std::chrono::milliseconds>(hours);
    auto minutes  = cast<std::chrono::minutes>(duration).count();
    duration     -= cast<std::chrono::milliseconds>(minutes);
    auto seconds  = cast<std::chrono::minutes>(duration).count();
    duration     -= cast<std::chrono::milliseconds>(seconds);

    std::cout << "The code took ";
    if (hours >= 1) {
        std::cout << std::lrint(hours) << "h";
    }
    if (minutes >= 1) {
        std::cout << std::lrint(minutes) << "m";
    }
    if (seconds >= 1) {
        std::cout << std::lrint(seconds) << "s";
    }
    if (milliseconds >= 1) {
        std::cout << std::lrint(duration) << "ms";
    }
    std::cout << " to execute\n";
}


int main() {
    std::chrono::high_resolution_clock::time_point start = start_timer();    
    /* do someting */
    stop_timer(start);
}
\$\endgroup\$
  • \$\begingroup\$ Ok, but my program does not only take into account milliseconds, but also seconds and minutes and provides also a way of specifying which function has just stopped, and to do nested calls. By the way, I'm using C++'s stl features to implement it. \$\endgroup\$ – nbro Oct 28 '16 at 11:16
  • \$\begingroup\$ Yes, but this does the same thing and you can easily cast that count to seconds miliseconds and whatever you want. \$\endgroup\$ – miscco Oct 28 '16 at 19:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.