How to get duration, as int milli's and float seconds from <chrono>?
Asked Answered
H

5

124

I'm trying to use chrono library for timers and durations.

I want to be able to have a Duration frameStart; ( from app start ) and a Duration frameDelta; ( time between frames )

I need to be able to get the frameDelta duration as milliseconds and float seconds.

How do you do this with the new c++11 <chrono> libraries? I've been working on it and googling ( information is sparse ). The code is heavily templated and requires special casts and things, I can't figure out how to use this library correctly.

Hawse answered 18/1, 2013 at 1:56 Comment(4)
Assign the duration to a duration with ratio seconds (or milliseconds) and then call count on it...Barbiturism
auto delta = duration_cast<seconds> (frameDelta).count(); Like this? It returns long long not a float.Hawse
@K-ballo, if the duration has a higher resolution than the type you assign it to then the assignment will be ill-formed, to avoid losing precision. You need to use a duration with a floating point representation, or use duration_castHoran
@JonathanWakely: Oh, then I have been using it wrong! :(Barbiturism
D
203

Is this what you're looking for?

#include <chrono>
#include <iostream>

int main()
{
    typedef std::chrono::high_resolution_clock Time;
    typedef std::chrono::milliseconds ms;
    typedef std::chrono::duration<float> fsec;
    auto t0 = Time::now();
    auto t1 = Time::now();
    fsec fs = t1 - t0;
    ms d = std::chrono::duration_cast<ms>(fs);
    std::cout << fs.count() << "s\n";
    std::cout << d.count() << "ms\n";
}

which for me prints out:

6.5e-08s
0ms
Doublet answered 18/1, 2013 at 2:33 Comment(14)
why not use auto on fs and d?Bartlett
@rhalbersma: Use of auto would be fine for d, as the result of the duration_cast<ms> is ms. However for fs auto would not be appropriate because the result of t1-t0 has type high_resolution_clock::duration which is not necessarily the same type as duration<float>. For example on my system it is duration<long long, nano>. So there's an implicit conversion from integral-based nanoseconds to float-based seconds happening on that line, only because the destination type is specified with fsec.Doublet
That's useful information. Just curious: would auto fs = std::chrono::duration_cast<fsec>(t1 - t0); be pedantic overkill?Bartlett
@rhalbersma: That would work just as well, and do the exact same thing. As to which should be preferred is entirely stylistic as far as I'm concerned.Doublet
be aware that in some real world scenarios (the ms compiler and libraries for instance) the 'high_resolution_clock' will miss times on the order of microseconds and this code will spit out zeroes,Fiddlestick
@jheriko: Yes, in that case you may want to consider rolling your own clock as demoed here: https://mcmap.net/q/20958/-c-cross-platform-high-resolution-timerDoublet
Rolling your own clock is probably overkill. If you just use the steady_clock instead that eliminates the issue of the clock being adjusted while you use it, and even on Windows the steady_clock has a resolution of nanoseconds, which is sufficient for most applications.Actuality
How would I define a float-duration in a unit other than seconds? It appears converting to other time units using duration_cast always returns integers...Euchromosome
@Nearoo: The return type of duration_cast<D> is D, whether D is integral based or floating point based. Example of float-based milliseconds: youtube.com/watch?v=P32hvk8b13M&t=28m49sDoublet
I'm slightly tangled up here: you do auto t0 = Time::now();. What will be the type of t0? It's not Time; I can't figure out what it is.Terebinthine
The type of t0 is the type returned by Time::now() which is std::chrono:: high_resolution_clock::time_point.Doublet
For basic usecases as getting duration in millis you not suppose to use duration_cast. To get duration in millis: std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0};Adam
THANK YOU for NOT using AUTO....i couldn't find any types for the return values because people keep using that typeless BS auto. please don't write instructions using AUTO,,,not everywhere i need to use your code I can type "auto' in...like return values of functions. 'auto' is JS typeless BS that ruins documentation. death to auto.Isham
Always auto everywhere. Type deduction is the best improvement to C++ in a long time.Gav
Z
33

Taking a guess at what it is you're asking for. I'm assuming by millisecond frame timer you're looking for something that acts like the following,

double mticks()
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    return (double) tv.tv_usec / 1000 + tv.tv_sec * 1000;
}

but uses std::chrono instead,

double mticks()
{
    typedef std::chrono::high_resolution_clock clock;
    typedef std::chrono::duration<float, std::milli> duration;

    static clock::time_point start = clock::now();
    duration elapsed = clock::now() - start;
    return elapsed.count();
}

Hope this helps.

Zellazelle answered 7/3, 2015 at 20:17 Comment(4)
Welcome to Stack Overflow. It would be great if you could provide aditional details to your code. It would help other people understand what you're trying to accomplish and how your solutions works. Thanks!Psychosis
FYI -- this was the CLEAREST, most useful example of the dozens I reviewed. Thanks for making the eternally-confusing chrono functions comprehendible.Herd
Why make start static? That can cause the compiler to put guards around it. Did you mean const instead?Grefe
Great! The only answer which does not use multiply/divide or duration_cast!!! To get duration in ms: std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0};Adam
H
18

I don't know what "milliseconds and float seconds" means, but this should give you an idea:

#include <chrono>
#include <thread>
#include <iostream>

int main()
{
  auto then = std::chrono::system_clock::now();
  std::this_thread::sleep_for(std::chrono::seconds(1));
  auto now = std::chrono::system_clock::now();
  auto dur = now - then;
  typedef std::chrono::duration<float> float_seconds;
  auto secs = std::chrono::duration_cast<float_seconds>(dur);
  std::cout << secs.count() << '\n';
}
Horan answered 18/1, 2013 at 2:15 Comment(4)
I guess he wants the actual count as a float?Barbiturism
That's what gets printed at the end. But I didn't know if he wants milliseconds as an integer, or milliseconds past the second, or what.Horan
I'd like to be able to get from a chrono::duration the duration represented as a int milliseconds, or float seconds(fraction of a second)Hawse
Howard's answer does exactly thatHoran
C
9

In AAA style using the explicitly typed initializer idiom:

#include <chrono>
#include <iostream>

int main(){
  auto start = std::chrono::high_resolution_clock::now();
  // Code to time here...
  auto end = std::chrono::high_resolution_clock::now();

  auto dur = end - start;
  auto i_millis = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
  auto f_secs = std::chrono::duration_cast<std::chrono::duration<float>>(dur);
  std::cout << i_millis.count() << '\n';
  std::cout << f_secs.count() << '\n';
}
Cynth answered 5/3, 2015 at 11:14 Comment(2)
For such simple case as getting duration in millis you not suppose to use duration _cast. To get duration in ms: std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0};Adam
@Adam who says "you not suppose to use duration_cast?" it seems to be a style question. You can either write in an almost-always-auto style and make the cast explicit or not use auto and make the cast implicitly. You are entitled to prefer one style over the other but its not like removing the duration_cast will make the code run faster.Cynth
T
0
float GetTimeFloat() {
    return std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(std::chrono::high_resolution_clock::now().time_since_epoch()).count() / 1000;
}
Threesquare answered 7/4, 2022 at 5:45 Comment(2)
Hi Reuniko! Thanks for contributing your answer, but in the future please try to avoid "code-only" answers and add some explanation around you code snippets, see How to Answer. Thanks!Trenton
each time you use multiply or divide with chrono - you do it wrong! Correct std::chrono::duration<double, std::milli> dur_in_ms{high_resolution_clock::now() - t0};Adam

© 2022 - 2024 — McMap. All rights reserved.