Xenonic
Xenonic

Reputation: 364

How to Make a Basic FPS Counter?

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

Answers (7)

satnhak
satnhak

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.

enter image description here

Upvotes: 1

Omar F. Kuri
Omar F. Kuri

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

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

user_number153
user_number153

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

user10015341
user10015341

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

CoffeDeveloper
CoffeDeveloper

Reputation: 8317

You have to sample 2 different time intervals using clock() however notes that there are several problems:

  • resolution of clock is several milliseconds (you may workaround using std::chrono etc, however even chrono may have not so high resolution depending on implementation. On my PC with GCC 4.9.1 I never get better resolution than 16 milliseconds even with std::chrono.
  • tipically using 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)
  • unless you are using vertical syncronization (vsync), you will not measure real frametime but just the CPU time spent in your render loop (to activate vsync you have to SetSwapInterval(1) wich your OS function or for example using a library like SDL that provide portable cross platform implementaiton)
  • To measure real rendering time you may use a GL'S time query (you may have only 1 timer bound at any time so if you are measuring framerate you cann't measure how long takes render something specific).
  • Do not measure FPS (well unless you want just to show it to users), instead measure frame time in milliseconds, that gives much more intuitive approximation of performance. (you know going from 100 to 80 FPS is 2,5 ms difference, going from 40 to 20 FPS is 25 ms difference!)

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

McLovin
McLovin

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

Related Questions