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.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
EddieV223
  • 5,085
  • 11
  • 36
  • 38
  • Assign the duration to a duration with ratio seconds (or milliseconds) and then call `count` on it... – K-ballo Jan 18 '13 at 02:07
  • auto delta = duration_cast (frameDelta).count(); Like this? It returns long long not a float. – EddieV223 Jan 18 '13 at 02:09
  • 3
    @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_cast` – Jonathan Wakely Jan 18 '13 at 02:18
  • @JonathanWakely: Oh, then I have been using it wrong! :( – K-ballo Jan 18 '13 at 02:20

5 Answers5

197

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
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 2
    why not use `auto` on `fs` and `d`? – TemplateRex Jan 18 '13 at 13:03
  • 28
    @rhalbersma: Use of `auto` would be fine for `d`, as the result of the `duration_cast` 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`. For example on my system it is `duration`. 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`. – Howard Hinnant Jan 18 '13 at 17:45
  • 2
    That's useful information. Just curious: would `auto fs = std::chrono::duration_cast(t1 - t0);` be pedantic overkill? – TemplateRex Jan 18 '13 at 18:18
  • 1
    @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. – Howard Hinnant Jan 18 '13 at 18:37
  • 2
    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, – jheriko Feb 28 '15 at 14:11
  • @jheriko: Yes, in that case you may want to consider rolling your own clock as demoed here: http://stackoverflow.com/a/5524138/576911 – Howard Hinnant Feb 28 '15 at 16:40
  • 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. – Neutrino Dec 15 '16 at 11:20
  • 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... – Nearoo Oct 15 '18 at 14:42
  • @Nearoo: The return type of `duration_cast` is `D`, whether `D` is integral based or floating point based. Example of float-based milliseconds: http://www.youtube.com/watch?v=P32hvk8b13M&t=28m49s – Howard Hinnant Oct 15 '18 at 15:03
  • 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. – Edward Falk Mar 24 '22 at 22:20
  • The type of `t0` is the type returned by `Time::now()` which is `std::chrono:: high_resolution_clock::time_point`. – Howard Hinnant Mar 24 '22 at 23:32
  • For basic usecases as getting duration in millis you not suppose to use duration_cast. To get duration in millis: std::chrono::duration dur_in_ms{high_resolution_clock::now() - t0}; – x4444 Jul 25 '23 at 23:00
32

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.

Billy The Kid
  • 321
  • 3
  • 3
  • 1
    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! – Luís Cruz Mar 07 '15 at 20:38
  • 4
    FYI -- this was the CLEAREST, most useful example of the dozens I reviewed. Thanks for making the eternally-confusing chrono functions comprehendible. – SMGreenfield Feb 18 '20 at 08:50
  • Why make `start` static? That can cause the compiler to put guards around it. Did you mean `const` instead? – ZachB Aug 23 '21 at 02:00
  • Great! The only answer which does not use multiply/divide or duration_cast!!! To get duration in ms: std::chrono::duration dur_in_ms{high_resolution_clock::now() - t0}; – x4444 Jul 25 '23 at 22:54
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';
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
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';
}
Chris Drew
  • 14,926
  • 3
  • 34
  • 54
  • For such simple case as getting duration in millis you not suppose to use duration _cast. To get duration in ms: std::chrono::duration dur_in_ms{high_resolution_clock::now() - t0}; – x4444 Jul 25 '23 at 22:56
  • @x4444 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. – Chris Drew Jul 31 '23 at 14:01
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;
}
  • 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! – joshmeranda Apr 07 '22 at 14:54
  • each time you use multiply or divide with chrono - you do it wrong! Correct std::chrono::duration dur_in_ms{high_resolution_clock::now() - t0}; – x4444 Jul 25 '23 at 22:53