I am trying to make a libary so that I can reuse all my class in future. Down here I have a class that can calculate delta time for fps and other stuffs if needed in future. I noticed that my first output of running always be a negative power up of -7 or more. Is it because I use float to do the calculation that it create this imprecision?
class Timer {
public:
Timer();
~Timer();
void Update();
float GetDeltaTime() const;
private:
std::chrono::time_point<std::chrono::high_resolution_clock> myCurrentTime;
std::chrono::time_point<std::chrono::high_resolution_clock> myLastTime;
};
Timer::Timer()
{
myCurrentTime = std::chrono::high_resolution_clock::now();
myLastTime = std::chrono::high_resolution_clock::now();
}
void Timer::Update()
{
myLastTime = myCurrentTime;
myCurrentTime = std::chrono::high_resolution_clock::now();
}
float Timer::GetDeltaTime() const
{
std::chrono::duration<float> deltaTime = std::chrono::duration_cast<std::chrono::duration<float> >(myCurrentTime - myLastTime);
return deltaTime.count();
}
int main()
{
Timer myTimer;
while (true) {
myTimer.Update();
std::cout << "Delta time: " << myTimer.GetDeltaTime() << std::endl; //Delta time: 2e-07 more or less it always become like this for first output
Sleep(1000);
}
}
Result
I tried to cast duration of time to float before the function run but it still produce same result
Related
Trying to write Singleton for the first time. This is a timer that works with one function to handle timer's both start and stop and also printing result.
When compiling, I'm getting linker errors like this one:
:-1: ошибка: CMakeFiles/some_algorithms.dir/timer_singleton.cpp.obj:timer_singleton.cpp:(.rdata$.refptr._ZN15timer_singleton7counterE[.refptr._ZN15timer_singleton7counterE]+0x0): undefined reference to `timer_singleton::counter'
What causes this error and how do I fix it?
Here is my source code:
timer_singleton.h
#ifndef TIMER_SINGLETON_H
#define TIMER_SINGLETON_H
#pragma once
#include <iostream>
#include <chrono>
class timer_singleton
{
public:
timer_singleton(timer_singleton & other) = delete;
void operator=(const timer_singleton& other) = delete;
static timer_singleton * getInstance();
static void hit_the_clock();
private:
timer_singleton();
static timer_singleton * instance;
static std::chrono::high_resolution_clock clock;
static std::chrono::high_resolution_clock::time_point start;
static std::chrono::high_resolution_clock::time_point stop;
static size_t counter;
};
#endif // TIMER_SINGLETON_H
timer_singleton.cpp
#include "timer_singleton.h"
timer_singleton::timer_singleton()
{
clock = std::chrono::high_resolution_clock();
start = clock.now();
stop = clock.now();
counter = 0;
}
timer_singleton * timer_singleton::getInstance()
{
if (instance == nullptr)
{
instance = new timer_singleton();
}
return instance;
}
void timer_singleton::hit_the_clock()
{
if (counter % 2 == 1)
{
// Clocks start ticking
start = clock.now();
++counter;
}
else
{
// Clocks stop ticking and print time measured time
stop = clock.now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
std::cout << "Measured time = " << duration.count() << " microseconds" << std::endl;
++counter;
}
}
main.cpp
#include "timer_singleton.h"
// ...
timer_singleton * timer = timer_singleton::getInstance();
timer->hit_the_clock();
// some calculations
timer->hit_the_clock();
The problem: Most non-constant static members need to be defined outside of the class definition in order to get the one-and-only-one instance that will be shared by all class instances. Normally this means that in timer_singleton.cpp you would have to add
timer_singleton::counter = 0; // allocate and initialize
But...
A singleton is effectively already static so the only static member should be the function that gets the instance. This makes the whole problem go away.
New code with comments about other useful changes:
class timer_singleton
{
public:
timer_singleton(timer_singleton &other) = delete;
void operator=(const timer_singleton &other) = delete;
static timer_singleton* getInstance();
void hit_the_clock(); // shouldn't be static
private:
timer_singleton();
// None of these should have been static
std::chrono::high_resolution_clock clock; // This clock could jump around,
// including backward, in time.
// Safer with a steady_clock
std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::time_point stop;
size_t counter;
};
timer_singleton::timer_singleton():
start(clock.now()),
stop(start), // guaranteed to be same as start
counter(0)
{ // assignments replaced with initializations in member initializer list
}
timer_singleton* timer_singleton::getInstance()
{ // now using Meyers singelton
static timer_singleton instance;
return &instance; // consider adjusting to return a reference.
// Often a bit cleaner thanks to the no null guarantee
}
void timer_singleton::hit_the_clock()
{
auto now = clock.now(); // if timing is critical, the first thing
// you do is get the current time.
//if (counter % 2 == 1) // remember counter starts at 0, so first hit
// would stop, not start, the timer.
if (counter % 2 == 0)
{
// Clocks start ticking
start = now;
}
else
{
// Clocks stop ticking and print time measured time
stop = now;
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
std::cout << "Measured time = " << duration.count() << " microseconds" << std::endl;
}
++counter; // don't repeat yourself
}
I have made a small header-only timer struct for testing the speed of functions. I made it purely out of curiosity because I am learning C++.
I have a function called "TimeTask" which has 2 overloads, The first one takes a std::function(void()) as a parameter and records how long the function takes to execute. The other one is a template function that takes a void function with any number of parameters and records its speed.
struct Timer
{
private:
std::chrono::steady_clock::time_point begin, end;
float Duration = 0.0f;
public:
const float& getDuration() const
{
return Duration;
}
void StartTimer()
{
begin = std::chrono::steady_clock::now();
}
void StopTimer()
{
end = std::chrono::steady_clock::now();
std::chrono::duration<float, std::milli> ChronoDuration = end - begin;
Duration = ChronoDuration.count();
}
template<class...Args>
void TimeTask(std::function<void(Args...)> task, Args&&...args)
{
StartTimer();
task(std::forward<Args>(args)...);
StopTimer();
}
void TimeTask(std::function<void()> task)
{
StartTimer();
task();
StopTimer();
}
};
Quite simple really. I tested it with the following code:
void task_parameters(double j) {
for (double i = 0; i < j * j * j * j * j; i++)
{
};
std::cout << "Done\n";
}
void task_void()
{
return;
}
int main()
{
Timer timer;
timer.TimeTask<double>(task_parameters,15.0);
std::cout << timer.getDuration() << std::endl;
timer.TimeTask(task_void);
std::cout << timer.getDuration() << std::endl;
std::cin.get();
return 0;
}
The program compiles and runs as expected but the first time I run the TimeTask function with "double" as my parameter type, it gives me an error:
E0304 no instance of overloaded function "Timer::TimeTask" matches the argument list
The program will still run, but I was wondering if I could get rid of this error? Thank you
The code appears to be correct and the behaves as expected, but I don't understand why that error is appearing.
The Problem: I'm writing a game (as a programming exercise) from scratch. I'm trying to limit the number of game logic loops ("ticks") per second. I've set it to an arbitrary 100 ticks/second. But no matter what I do, it seems to run at ~130 ticks/second. Could it possibly be rounding errors adding up? Something else? Thanks in advance for any help you can give.
Note: my codebase is much larger than this, but for the purposes of this question, I've stripped it down as much as possible without breaking the rate limiter.
The Output:
counter 1 sleep_for(5ms)
counter 2 sleep_for(2ms)
[snip]
counter 132 sleep_for(3ms)
counter 133 sleep_for(3ms)
133 TPS last 1003ms
counter 134 sleep_for(3ms)
counter 135 sleep_for(3ms)
[snip]
counter 265 sleep_for(3ms)
counter 266 sleep_for(3ms)
133 TPS last 1004ms
counter 267 sleep_for(3ms)
counter 268 sleep_for(3ms)
[snip]
counter 399 sleep_for(3ms)
counter 400 sleep_for(3ms)
134 TPS last 1006ms
The Code:
(The two main functions to look at are ThreadRateLimiter::Tock() and TickRateCounter::Tock())
#include <chrono>
#include <exception>
#include <fstream>
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
const int TICK_RATE = 100;
const chrono::milliseconds TIME_PER_TICK =
chrono::duration_cast<chrono::milliseconds>(chrono::seconds(1)) / TICK_RATE;
template <class T>
class TickTocker
{
public:
virtual void Tick() = 0;
virtual T Tock() = 0;
virtual T TickTock()
{
Tick();
return Tock();
}
};
Ticker:
class Ticker : public TickTocker<long>
{
public:
friend ostream& operator<<(ostream& stream, const Ticker& counter);
Ticker() :
Ticker(0)
{}
Ticker(long counter) :
mTicks(counter),
mTicksLast(mTicks)
{}
Ticker(const Ticker& counter) :
Ticker(counter.mTicks)
{}
bool operator==(const long i)
{
return mTicks == i;
}
void Tick() override
{
mTicks++;
}
long Tock() override
{
long diff = mTicks - mTicksLast;
mTicksLast = mTicks;
return diff;
}
// private:
long mTicks;
long mTicksLast;
};
ostream& operator<<(ostream& stream, const Ticker& counter)
{
return (stream << "counter " << counter.mTicks);
}
TickTracker:
class TickTracker : public TickTocker<chrono::milliseconds>
{
public:
TickTracker() :
mTime(chrono::steady_clock::now()),
mLastTime(mTime)
{}
void Tick() override
{
mTime = chrono::steady_clock::now();
}
chrono::milliseconds Tock() override
{
chrono::milliseconds diff = chrono::duration_cast<chrono::milliseconds>(mTime - mLastTime);
mLastTime = mTime;
return diff;
}
protected:
chrono::time_point<chrono::steady_clock> mTime;
chrono::time_point<chrono::steady_clock> mLastTime;
};
ThreadRateLimiter:
class ThreadRateLimiter : public TickTracker
{
public:
ThreadRateLimiter() : TickTracker(),
mMsFast(chrono::milliseconds(0))
{}
void Tick() override
{
mCounter.Tick();
TickTracker::Tick();
if (mCounter == 1)
{
TickTracker::Tock();
}
}
chrono::milliseconds Tock()
{
chrono::milliseconds diff = TickTracker::Tock();
chrono::milliseconds remaining = TIME_PER_TICK - diff;
/*
* If we always sleep the full remaining time, we'll alternate between sleeping for "minimum" and "maximum" sleep
* times. Sleeping the full remaining time only when we exceed the average makes for more stable sleep times.
*/
bool fullSleep = (mMsFast.count() > (TIME_PER_TICK.count() / 2));
mMsFast += remaining;
if (mMsFast.count() > 0)
{
chrono::milliseconds sleep = fullSleep ? mMsFast : (chrono::milliseconds(mMsFast.count() / 2));
cout << mCounter << " sleep_for(" << sleep.count() << "ms)" << endl;
this_thread::sleep_for(mMsFast);
mMsFast -= sleep;
}
mCounter.Tock();
return remaining;
}
private:
Ticker mCounter;
chrono::milliseconds mMsFast;
};
TickRateCounter:
class TickRateCounter : public TickTracker
{
public:
TickRateCounter(string rateLabel) : TickTracker(),
mRateLabel(rateLabel)
{}
void Tick() override
{
mCounter.Tick();
TickTracker::Tick();
}
chrono::milliseconds Tock() override
{
if (chrono::duration_cast<chrono::seconds>(mTime - mLastTime).count() >= 1)
{
chrono::milliseconds duration = TickTracker::Tock();
cout << (mCounter.Tock() / chrono::duration_cast<chrono::seconds>(duration).count()) << " " << mRateLabel
<< " last " << duration.count() << "ms" << endl;
return duration;
}
return chrono::milliseconds(0);
}
// private:
Ticker mCounter;
string mRateLabel;
};
Main:
int main()
{
ThreadRateLimiter mRateLimiter;
TickRateCounter mTpsCounter("TPS"); // TPS = Ticks per second. Tick = one game loop
while (mTpsCounter.mCounter.mTicks < 400)
{
mRateLimiter.TickTock();
mTpsCounter.TickTock();
}
return 0;
}
The proper way to have rate limiting is:
//pseudocode follows
const frame_duration = something;
last = now();
while(true)
{
process_your_frame_here()
do
{
t = now();
sleep(0); // or whatever fits your system
}
while(t < last + frame_duration);
last = last + frame_duration; // THIS IS KEY
// last = now; // would not produce the right framerate
}
Basically, you delay your frame, as you seem to do. But when bookkeeping the time spent, you only add the time you wanted (frame_duration). So, over multiple frame, it evens out.
To elaborate, if now() starts at 1000 (whatever unit) and you set frame_duration to 200, frame 1 will only run after 1200, frame 2 after 1400, ... frame 100 after 20100, giving exact frame rates over long periods of time.
In c++ how do I successfully chain classes together in the following example?
Clock timer;
std::cout << timer.getElapsedTime().inSeconds();
std::cout << timer.getElapsedTime().inMilliseconds();
How do I write the code successfully?
class ElapsedTime
{
private:
double _start;
public :
ElapsedTime(double start)
{
_start = start;
}
double inSeconds() const
{
return (std::clock() - _start ) / (double) CLOCKS_PER_SEC;
}
double inMilliseconds() const
{
return ((std::clock() - _start ) / (double) CLOCKS_PER_SEC) * 1000;
}
};
class Clock
{
private:
std::clock_t _start;
double _duration;
public:
Clock()
{
_start = std::clock();
}
ElapsedTime getElapsedTime() const {
return ElapsedTime(_start);
}
double reset()
{
_duration = (std::clock() - _start ) / (double) CLOCKS_PER_SEC;
_start = std::clock();
return _duration;
}
};
edit: made the suggested changes by pm100
Although the class chain still returns a value like .7e-05
and if I try to use const in the following manner I get a segmentation fault
ElapsedTime const& getElapsedTime() const {
return ElapsedTime(_start);
if you want to make it work this way, which is odd. You need a constructor for ElapsedTime that takes start
class ElapsedTime
{
double _start;
public :
ElapsedTime(double start)
{
_start = start;
}
(use _start in the rest of the code)
Then in clock
ElapsedTime getElapsedTime() const {
return ElapsedTime(start);
}
Your variable "start" is declared within the scope of your class Clock. It isn't defined within the scope of your class ElapsedTime.
Why don't you define a method ElapsedTime in your Clock class rather than using 2 classes?
If I were writing this code, I probably would not make ElapsedTime its own class. I think I would just add getElapsedTimeInSeconds() and getElapsedTimeInMilliseconds() to the Clock class, like so:
class Clock
{
public:
Clock()
{
start = std::clock();
}
double getElapsedTimeInSeconds() const
{
return (std::clock() - start) / (double) CLOCKS_PER_SEC;
}
double getElapsedTimeInMilliseconds() const
{
return getElapsedTimeInSeconds() * 1000;
}
double reset()
{
duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;
start = std::clock();
return duration;
}
protected:
std::clock_t start;
private:
double duration;
};
and then the main function:
int main(void)
{
Clock timer;
std::cout << timer.getElapsedTimeInSeconds() << std::endl;
std::cout << timer.getElapsedTimeInMilliseconds() << std::endl;
}
I dont know how you call it.. After you compile with visual studio10, black screen pops up and displays the results.
I have noticed on youtube videos that on their screen, it also displays how long it took to calculate.(not compiling time)
Im pretty sure the answer is out there but I dont know the keywords for searching..
Here's a little stopwatch class I use to time things. Accuracy is ... well ... it gets better the more work you're doing, put it that way.
#include <sstream>
#include <chrono>
class Stopwatch final
{
public:
Stopwatch()
{
Reset();
}
void Reset()
{
MyCurrentTime = MyClock.now();
}
double Elapsed() const
{
auto elapsed = std::chrono::duration_cast<std::chrono::duration<double>>(MyClock.now() - MyCurrentTime);
return elapsed.count();
}
int ms() const
{
return static_cast<int>(0.5 + Elapsed() * 1000);
}
std::string ToMilliseconds() const
{
auto o = std::ostringstream();
o << ms();
return o.str();
}
std::string ToSeconds(int precision) const
{
auto o = std::ostringstream();
o.precision(precision);
o << std::fixed << Elapsed();
return o.str();
}
private:
std::chrono::high_resolution_clock MyClock;
std::chrono::high_resolution_clock::time_point MyCurrentTime;
};
A small example:
omp_get_wtime
#include <omp.h>
int main(void)
{
double dStart = omp_get_wtime();
Calculations();
double dEnd = omp_get_wtime();
std::cout << "Calculation took: " << dEnd - dStart << " sec." std::endl;
return 0;
}