Penrose5833
Penrose5833

Reputation: 107

Chrono C++ to give realtime elapsed time

Here is a clear question: can you provide a simple example of chrono being called from main (or its own class) and used in another class. Or a link to an example.

and below is me fumbling around trying to explain my problem in more detail:

I have been working on this all day and keep ending up in the same place. I am writing a program that is supposed to output the elapsed time after certain processes finish. The problem I am having is that these processes are happening in different classes and I cannot get the clock to work properly. I keep reverting back to having the clock in the main but am really struggling to make everything mesh together. So maybe this is a simple question about working with classes. But there is something about I am not understanding and I don't know what it is.

Below are the 4 lines of this timer that I keep reverting back to and placing in my main function. It prints the clock how I want in the format x.xxxxxx

auto clock_start = chrono::system_clock::now();
auto clock_now = chrono::system_clock::now();
float currentTime = float(chrono::duration_cast <chrono::microseconds> (clock_now - clock_start).count());
cout << "Elapsed Time: " << currentTime /1000000 << " S \n";

Eventually, I have a queue of structs that im popping in a loop that I then manipulate. They need a time-stamp when printed at the end of each loop iteration. I just can't for the life of me get the timer to give the time elapsed (or even work) while in the loop.

is this possible? I have read many threads on chrono and something is just not clicking for me when I try using the timer in multiple classes/functions across my program.

EDIT***

SO here is my current class in my meta.h: These are private members inside class Meta

typedef std::chrono::system_clock timer;
timer::time_point currentTime;
timer::time_point startTime;
timer::time_point clock_wait;
timer::time_point clock_check;
timer::time_point elapsed_time; // this is my issue

And then I start the time in meta.cpp

 void Meta::startTimer()
      {
           startTime = timer::now();
      }

And here is the loop with some pieces missing so we can focus on the timer:

 void Meta::displaySim()
 {
     //auto clock_start = chrono::system_clock::now(); THIS IS WHAT I WAS DOING
queue<sData>newFile;

while (!MetaQ.empty())
{
    temp = MetaQ.front();
    bool wait = true;
    float waitTime = float(temp.ncycle)/1000;
    while (wait)
    {
        clock_wait = timer::now();
        clock_check = timer::now();
        elapsed_time = timer::duration_cast<chrono::milliseconds>(clock_check - clock_wait);
        if (elapsed_time.count() > waitTime)
            wait = false;

    }
    cout << "****" << waitTime << "*****"<< endl;
    end_time = timer::now();
 //Below is the line that is giving me trouble now. I get an error when casting. I don't know how to make duration_cast part of the timer declared in meta.h
    float EndTime = float(timer::duration_cast <chrono::milliseconds>(end_time - startTime).count());
    cout << fixed << EndTime / 1000000  << " - (" << temp.desc << ')' << temp.cycle << " - " << temp.ncycle << " ms\n";
    newFile.push(temp);
    MetaQ.pop();
}

MetaQ = newFile;

}

Upvotes: 4

Views: 11949

Answers (1)

Howard Hinnant
Howard Hinnant

Reputation: 219345

timer::time_point elapsed_time; // this is my issue

Just from the name elapsed_time, this doesn't sound like a time_point. It sounds like a duration. Do this to fix that problem:

timer::duration elapsed_time;

This looks suspicious:

float waitTime = float(temp.ncycle)/1000;

Typically a time duration should have type std::chrono::duration<some representation, some period>. And you don't want to apply conversion factors like 1/1000 manually. Let <chrono> handle all conversions.

elapsed_time = timer::duration_cast<chrono::milliseconds>(clock_check - clock_wait);

duration_cast is not a static member function of system_clock. duration_cast is a namespace scope function. Use it like this:

elapsed_time = chrono::duration_cast<chrono::milliseconds>(clock_check - clock_wait);

If waitTime had a duration type, the .count() would be unnecessary here:

if (elapsed_time.count() > waitTime)

// Below is the line that is giving me trouble now. I get an error when casting.
// I don't know how to make duration_cast part of the timer declared in meta.h
float EndTime = float(timer::duration_cast <chrono::milliseconds>(end_time - startTime).count());

Best practice is to stay within the <chrono> type system instead of escaping to scalars such as float. You can get integral milliseconds with this:

auto EndTime = chrono::duration_cast<chrono::milliseconds>(end_time - startTime);

If you really want EndTime to be float-based milliseconds, that is easy too:

using fmilliseconds = chrono::duration<float, std::milli>;
fmilliseconds EndTime = end_time - startTime;

For more details, here is a video tutorial for the <chrono> library: https://www.youtube.com/watch?v=P32hvk8b13M


If this answer doesn't address your question, distill your problem down into a complete minimal program that others can copy/paste into their compiler and try out. For example I could not give you concrete advice on waitTime because I have no idea what temp.ncycle is.


Finally, and this is optional, if you would like an easier way to stream out durations for debugging purposes, consider using my free, open source, header-only date/time library. It can be used like this:

#include "date/date.h"
#include <iostream>
#include <thread>

using timer = std::chrono::system_clock;
timer::time_point clock_wait;
timer::time_point clock_check;
timer::duration elapsed_time;

int
main()
{
    using namespace std::chrono_literals;
    clock_wait = timer::now();
    std::this_thread::sleep_for(25ms); // simulate work
    clock_check = timer::now();
    elapsed_time = clock_check - clock_wait;
    using date::operator<<;  // Needed to find the correct operator<<
    std::cout << elapsed_time << '\n';  // then just stream it
}

which just output for me:

25729µs

The compile-time units of the duration are automatically appended to the run-time value to make it easier to see what you have. This prevents you from accidentally appending the wrong units to your output.

Upvotes: 6

Related Questions