Reputation: 364
I'm trying to display my frames-per-second in my cube-rendering program. I would like to see its performance. So, how can I do it? I have done research on this already, but the examples I've seen use either multiple classes and still don't work, or they use libraries that I don't have. Is there a way to get the FPS by using pre-installed libs like ctime? I am using OpenGL with C++.
Here is my (empty) function:
void GetFPS()
{
}
and then I display my FPS in my render function with:
std::cout << xRot << " " << yRot << " " << zRot << " " << FPS << "\n"; //xRot, yRot, and zRot are my cube's rotation.
My program is set to 60FPS, but I would like to see the actual FPS, not what it's set to.
Upvotes: 12
Views: 59964
Reputation: 9861
What I wanted was a framerate that is sufficiently accurate, but also doesn't jump around too much, so what i came up with was calculating the frames during an interval (like 100ms) and then smoothing that over a window (like the last 10 intervals, so 1 second).
#include <chrono>
#include <cmath>
template <uint16_t Window>
class RollingAverage
{
private:
uint16_t m_index = 0;
uint16_t m_count = 0;
uint32_t m_previous_inputs[Window];
uint64_t m_sum = 0;
public:
uint32_t operator()(uint32_t input, double factor = 1.0)
{
m_sum -= m_previous_inputs[m_index];
m_sum += input;
m_previous_inputs[m_index] = input;
if (++m_index == Window) m_index = 0;
return static_cast<uint32_t>(
std::lround((factor * m_sum) / (m_count < Window ? ++m_count : Window)));
}
};
template <uint16_t Window = 10, uint32_t IntervalMS = 100>
class FrameCounter
{
private:
RollingAverage<Window> m_rolling_average;
std::chrono::time_point<std::chrono::high_resolution_clock> m_previous_time;
uint32_t m_previous_frame_count = 0;
uint32_t m_frame_count = 0;
uint32_t m_fps = 0;
public:
void next_frame()
{
m_frame_count++;
auto current_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - m_previous_time);
if (duration.count() >= IntervalMS)
{
m_fps = m_rolling_average(m_frame_count - m_previous_frame_count, 1000.0 / IntervalMS);
m_previous_frame_count = m_frame_count;
m_previous_time = current_time;
}
}
uint32_t fps() const { return m_fps; }
};
With the default settings (i.e. FrameCounter<>
) it calculates the number of frames over the last 100ms and then smooths that over a 1 second window. This seems to work pretty well. You can see what it looks like without smoothing by setting the window to 1
(i.e. FrameCounter<1>
) and it's not quite as easy on the eye.
Upvotes: 1
Reputation: 38
I couldn't get any of these to work. Here is my solution using this method for getting ms.
// Gets the time in milliseconds
#include <chrono>
typedef std::chrono::system_clock Clock;
auto ms() {
auto now = Clock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(fraction);
return milliseconds.count();
}
// Main loop
auto prevTime = ms();
while (running) {
frames++;
processRender();
if (deltaTime >= 1000) {
// Do something here every second
second();
deltaTime = 0;
frames = 0;
}
auto currTime = ms();
diff = currTime - prevTime;
if (diff > 0) {
deltaTime += diff;
}
prevTime = currTime;
}
Upvotes: 0
Reputation: 49
Fast and complete
#include <time.h> // clock
#include <stdio.h> // snprintf
unsigned int iMemClock, iCurClock, iLoops;
char aFPS[12];
/* main loop */
{
if (iMemClock > (iCurClock = clock()))
iLoops++;
else
{
snprintf(aFPS, sizeof(aFPS),"FPS: %d",iLoops);
iMemClock = iCurClock + CLOCKS_PER_SEC;
iLoops = 0;
}
/*
someRoutines();
*/
}
/* main loop */
Upvotes: 0
Reputation: 562
just call this in any loop to measure the number of calls a second.
#include <chrono>
void printFPS() {
static std::chrono::time_point<std::chrono::steady_clock> oldTime = std::chrono::high_resolution_clock::now();
static int fps; fps++;
if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - oldTime) >= std::chrono::seconds{ 1 }) {
oldTime = std::chrono::high_resolution_clock::now();
std::cout << "FPS: " << fps << std::endl;
fps = 0;
}
}
Upvotes: 5
Reputation:
If you want to measure FPS only for the sake of printing it, you may use std::chrono
as it measures wall clock. Using std::clock()
results in a more accurate value than std::chrono
since it measures processing time, but maybe you don't want to print FPS with such a high precision.
The solution below uses std::chrono
to calculate a program's uptime and increments a frame counter after each frame update. Dividing the frame counter by the program's uptime gives you the FPS.
#include <chrono>
#include <iostream>
#include <thread>
using namespace std::chrono;
steady_clock::time_point first_tp;
unsigned long frame_count = 0;
duration<double> uptime()
{
if (first_tp == steady_clock::time_point{})
return duration<double>{ 0 };
return steady_clock::now() - first_tp;
}
double fps()
{
const double uptime_sec = uptime().count();
if (uptime_sec == 0)
return 0;
return frame_count / uptime_sec;
}
void time_consuming_function()
{
std::this_thread::sleep_for(milliseconds{ 100 });
}
void run_forever()
{
std::cout << "fps at first: " << fps() << '\n';
first_tp = std::chrono::steady_clock::now();
while (true)
{
std::cout << "fps: " << fps() << '\n';
time_consuming_function();
frame_count++;
}
}
int main()
{
run_forever();
}
Running it on my machine produces:
$ ./measure_fps
fps at first: 0
fps: 0
fps: 9.99108
fps: 9.99025
fps: 9.98997
fps: 9.98984
Whereas adapting it to std::clock()
gives
$ ./measure_fps
fps at first: 0
fps: 0
fps: 37037
fps: 25316.5
fps: 23622
fps: 22346.4
Upvotes: 0
Reputation: 8317
You have to sample 2 different time intervals using clock()
however notes that there are several problems:
clock()
you will get 0 many times and at some time you will measure a real time (in my case it just make a jump of 15/16 milliseconds)Do that:
double clockToMilliseconds(clock_t ticks){
// units/(units/time) => time (seconds) * 1000 = milliseconds
return (ticks/(double)CLOCKS_PER_SEC)*1000.0;
}
//...
clock_t deltaTime = 0;
unsigned int frames = 0;
double frameRate = 30;
double averageFrameTimeMilliseconds = 33.333;
while(rendering){
clock_t beginFrame = clock();
render();
clock_t endFrame = clock();
deltaTime += endFrame - beginFrame;
frames ++;
//if you really want FPS
if( clockToMilliseconds(deltaTime)>1000.0){ //every second
frameRate = (double)frames*0.5 + frameRate*0.5; //more stable
frames = 0;
deltaTime -= CLOCKS_PER_SEC;
averageFrameTimeMilliseconds = 1000.0/(frameRate==0?0.001:frameRate);
if(vsync)
std::cout<<"FrameTime was:"<<averageFrameTimeMilliseconds<<std::endl;
else
std::cout<<"CPU time was:"<<averageFrameTimeMilliseconds<<std::endl;
}
}
The above code works also when you do something that takes several seconds. I do a computation that is updated every second, you could as well update it more often. (note I use exactly that code in most of my projects that need FPS)
Upvotes: 21
Reputation: 3417
Simply save the time "ticks" before and after you render your scene, then do a simple calculation.
Here's an example that uses <ctime>
's clock()
function. (note that clock()
works differently on different platform)
clock_t current_ticks, delta_ticks;
clock_t fps = 0;
while(true)// your main loop. could also be the idle() function in glut or whatever
{
current_ticks = clock();
render();
delta_ticks = clock() - current_ticks; //the time, in ms, that took to render the scene
if(delta_ticks > 0)
fps = CLOCKS_PER_SEC / delta_ticks;
cout << fps << endl;
}
Upvotes: 9