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 withstd::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 theTick
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 partialdelta
'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):
system_clock
: This measures Unix Time (time since 1970 excluding leap seconds).1steady_clock
: Like a stop-watch. Great for timing, but it can not tell you the time of day.high_resolution_clock
: This has the disadvantages ofsystem_clock
andsteady_clock
, and the advantages of neither. Typically it is a type alias to eithersystem_clock
orsteady_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 tohigh_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
How to Detect Win32 Process Creation/Termination in C++
Initialize a Const Array in a Class Initializer in C++
What Does Opencv'S Cvwaitkey( ) Function Do
Copy Constructor For a Class With Unique_Ptr
Rand() % 14 Only Generates the Values 6 or 13
How to Get Available Memory C++/G++
When Passing an Array to a Function in C++, Why Won't Sizeof() Work the Same as in the Main Function
How Many and Which Are the Uses of "Const" in C++
Smart Pointers: Who Owns the Object
How to Search/Find and Replace in a Standard String
Is It a Good Practice to Place C++ Definitions in Header Files
How to Do an Integer Log2() in C++
Static Constructors in C++? I Need to Initialize Private Static Objects
Global Variable Within Multiple Files