What Are the Uses of Std::Chrono::High_Resolution_Clock

What are the uses of std::chrono::high_resolution_clock?

There are none.

Sorry, my bad.

If you are tempted to use high_resolution_clock, choose steady_clock instead. On libc++ and VS high_resolution_clock is a type alias of steady_clock anyway.

On gcc high_resolution_clock is a type alias of system_clock and I've seen more than one use of high_resolution_clock::to_time_t on this platform (which is wrong).

Do use <chrono>. But there are parts of <chrono> that you should avoid.

  • Don't use high_resolution_clock.
  • Avoid uses of .count() and .time_since_epoch() unless there is no other way to get the job done.
  • Avoid duration_cast unless the code won't compile without it, and you desire truncation-towards-zero behavior.
  • Avoid explicit conversion syntax if an implicit conversion compiles.

std::chrono::high_resolution_clock based frame timer

For practical purposes, you only have 3 choices:

  • For taking real time, your only choice is std::system_clock (if you want to stay inside C++, OS levels routines do exist)
  • For measuring intervals, if you want to stay within C++, you have to use std::steady_clock. There is no implementation out there which would have a steady clock with resolution higher than you get with std::steady_clock
  • Viable alternative to above if you are eager to sacrifice C++ conformance is using TSC counters directly. This is highest possible resolution one can ever see and is also the fastest to use. The downside is that if you want to measure units of time rather than cycles, you'd have to convert cycles to seconds using CPU cycle rate.

How to declare a variable for high resolution clock in C++?

std::chrono::high_resolution_clock::time_point orderRecvedTime;

In practice, high_resolution_clock is a type alias for either system_clock or steady_clock, so my advice is to choose either one of those instead for a portable experience.

  • system_clock is like a watch. It can tell you what time it is.
  • steady_clock is like a stop watch. It is really good for timing things, but doesn't really know the time of day.

C++11 chrono high_resolution_clock steadyness in busy loop?

So, after some digging, it is revealed that the delta computation logic together with how now is used are flawed. Several points:

  • now should only be recorded once entering the Tick function and used across the entire scope
  • the original code essentially only measures sub-parts of the entire time line as delta, that's why the accumulation of the partial delta's is less than the actual time elapsed, thus it appeared that the time is extended more than the actual time line!

The working code looks like below:

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

std::chrono::high_resolution_clock::time_point then{};

double accumulator = 0.0;
size_t count = 0;

void Tick()
{
auto now = std::chrono::high_resolution_clock::now(); // the time point of this tick

if (then != std::chrono::high_resolution_clock::time_point{}) {
auto delta = std::chrono::duration<double>(now - then).count(); // should use the recorded time point 'now'
accumulator += delta;
++count;
if (accumulator >= 1.0) {
std::cout << "count: " << count << " | average delta: " << 1.0 / count << std::endl;
accumulator = 0.0;
count = 0;
}
} else {
std::cout << "###" << std::endl;
}
then = now; // should use the recorded time point as this tick time
}

int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
while (true) {
Tick();

// other processing
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return 0;
}

C++ std::chrono::high_resolution_clock time_since_epoch returns too small numbers. How can I get the correct time since 1970 in microseconds?

There are three chrono-supplied clocks in C++11/14/17 (more in C++20):

  1. system_clock: This measures Unix Time (time since 1970 excluding leap seconds).1

  2. steady_clock: Like a stop-watch. Great for timing, but it can not tell you the time of day.

  3. high_resolution_clock: This has the disadvantages of system_clock and steady_clock, and the advantages of neither. Typically it is a type alias to either system_clock or steady_clock, and which one differs with platform.

You have to use system_clock for measuring time since 1970. Note that this is measured in UTC, not your local time zone. In C++11/14/17 to get the local time since 1970, you will have to either manually take your time zone into account, or use this C++20 chrono preview library.

std::int64_t
NowInMicroseconds()
{
using namespace std::chrono;
return duration_cast<microseconds>(system_clock_clock::now().time_since_epoch()).count();
}

Consider returning a strong type which means "microseconds since 1970" instead of an integral type. Strong type safety helps you find your logic errors at compile time:

std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>
NowInMicroseconds()
{
using namespace std::chrono;
return time_point_cast<microseconds>(system_clock.now());
}

1 This is unspecified in C++11/14/17, but is true on all implementations. C++20 finally nails this epoch down in the spec.

platform-specific std::chrono::high_resolution_clock::period::num

There are three implementations of std::chrono::high_resolution_clock that I am aware of: Visual Studio, gcc and clang (when used with libc++).

All three of these have nanosecond-precision (std::chrono::high_resolution_clock::period::num = 1). For VS and libc++, high_resolution_clock is type-aliased to steady_clock. On gcc it is type-aliased to system_clock.

There is nothing in the spec that prevents std::chrono::high_resolution_clock::period::num != 1, and you are correct that on such a system 1 second would not be representable in "ticks". This further translates to:

seconds would not be implicitly convertible to high_resolution_clock::duration.

To find the coarsest duration to which both seconds and high_resolution_clock::duration are convertible to, you can portably use:

using CT = common_type_t<seconds, high_resolution_clock::duration>;

For all of the implementations I'm aware of, CT is a type-alias for nanoseconds.

C++ use std::chrono to measure execution of member functions in a nice way

You could create a class like:

struct MeasureTime {
MeasureTime() : _start(std::chrono::high_resolution_clock::now()) {}

~MeasureTime() {
auto stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = stop - _start;
std::cout << duration.count() * 1000 << "ms\n";
}
private:
std::chrono::time_point<std::chrono::high_resolution_clock> _start;
};

and simply use it in your code:

Test::Test()
{
MeasureTime mt;
[...]
{ //or even this for just the init call
MeasureTime mt2;
int value = init(1, 1.2);
}
}

IMHO it is less intrusive than what you proposed.

If you really want a function, you may try a wrapper like:

template <class T, class F, class... Args>
auto MeasureTimeFn(T *t, F &&fn, Args&&... args) {
MeasureTime timer;
return (t->*fn)(std::forward<Args>(args)...);
}

And call it like:

int value = MeasureTimeFn(this, &Test::init, 1, 1.2);

but not sure it is really much better.

You can try to hide thing with a macro:

#define MEASURE(f, ...) \
MeasureTimeFn(this, &std::remove_reference_t<decltype(*this)>::f, __VA_ARGS__)

this way you can write

int value = MEASURE(init, 1, 1.2);

what is quite like what you asked for, but only works inside member functions, with member functions (non static).

Anyway probably a good place to start with.

* EDIT*
If you can modify inheritance of you class, you may try

template<class T>
struct MeasureTool {
template <class F, class... Args>
auto measure(F &&fn, Args&&... args) {
tools::TimeMeasure timeMeasure;
return (static_cast<T*>(this)->*fn)(std::forward<Args>(args)...);
}
};

class Test : public MeasureTool<Test>
{
public:
Test();
virtual ~Test() {}
int init(const std::string &filepath) { _path = filepath; return 0; }
const auto &getPath() const { return _path; }
private:
std::string _path;

};

Test::Test()
{
std::string filepath("/some/where");
int value = measure(&Test::init, filepath);
measure(&Test::getPath);
}

And, this time, seems to match your very first requirement (but is quite intrusive...)

now, it's all in your hands :)

using std::chrono::high_resolution_clock to write a frame 30 times per second

There is a basic tenant to working with chrono, which goes something like:

If you use count(), and/or you have conversion factors in your
chrono code, then you're trying too hard.

This is not your fault. There really is no good chrono tutorial and that is my bad, and I've recently decided I need to do something about that.

In your case, I recommend rewriting your code along the lines of the following:

First create a duration unit which represents the period of your frame rate:

using frame_period = std::chrono::duration<long long, std::ratio<1, 30>>;

Now when you say frame_period{1}, that means exactly 1/30 of a second.

The next thing to note is that chrono comparisons are always exact, as long as you stay in the chrono system. count() is a "trap door" for escaping out of the chrono system. Only escape out when you have no other choice. So...

auto prev = std::chrono::high_resolution_clock::now();
auto current = pref;
// Just get the difference, and don't worry about the units for now
auto difference = current-prev;
while(recording)
{
// Find out if the difference is less than one frame period
// This comparison will do all the conversions for you to get an exact answer
while (difference < frame_period{1})
{
current = std::chrono::high_resolution_clock::now();
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.write(frameToRecord);
// This is a little tricky...
// prev + frame_period{1} creates a time_point with a complicated unit
// Use time_point_cast to convert (via truncation towards zero) back to
// the "native" duration of high_resolution_clock
using hr_duration = std::chrono::high_resolution_clock::duration;
prev = std::chrono::time_point_cast<hr_duration>(prev + frame_period{1});
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.release();

The comments above are overly verbose once you get chrono. There's more comment than code above. But the above just works as you intended, with no need for "escaping out" of the chrono system.

Update

If you would want to initialize difference such that the inner loop won't be executed the first time, you could initialize it to something just over frame_period{1} instead of to 0. To do this, the utilities found here come in handy. Specifically ceil:

// round up
template <class To, class Rep, class Period>
To
ceil(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t < d)
++t;
return t;
}

ceil is a replacement for duration_cast that will round up when the conversion is inexact, as opposed to truncate towards zero. Now you can say:

auto difference = ceil<hr_duration>(frame_period{1});

And you are guaranteed that difference >= frame_period{1}. Furthermore, it is known in practice that the duration of high_resolution_clock is nanoseconds, thus you can deduce (or test) that difference is actually initialized to 33,333,334ns, which is 2/3 of a nanosecond greater than 1/30 of a second, which equals frame_period{1}, which equals 33,333,333+1/3ns.



Related Topics



Leave a reply



Submit