11

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.

Garrett Hyde
  • 5,409
  • 8
  • 49
  • 55
Xenonic
  • 346
  • 2
  • 3
  • 20
  • What OS are you running? Different OS' s may require different code. – K_Finlay Feb 15 '15 at 22:06
  • I am using Windows, sorry I forgot to mention that. – Xenonic Feb 15 '15 at 22:09
  • May I suggest having a look at time class for my engine: https://github.com/BlackRainInteractive/Splash/tree/master/Splash!/Source/splSystem/Time – K_Finlay Feb 15 '15 at 22:34
  • It does use a few functions / classes, but it should help you figure out how to implement your own. Edit: I would post a stripped down version as an answer, but doing that on a tablet is a bit time consuming. – K_Finlay Feb 15 '15 at 22:35
  • the problem with the other answer is division by 0, apart that is correct (of course since you will have a time of 0 90% of frame that-s a bit problematic, see my answer) – CoffeDeveloper Feb 16 '15 at 15:14
  • Possible duplicate of [How to calculate FPS in OpenGL?](http://stackoverflow.com/questions/5627803/how-to-calculate-fps-in-opengl) – Ciro Santilli OurBigBook.com Mar 19 '16 at 11:17
  • The possible duplicate shows one possible way to get a crude approximation to the value. The answers here are more complete, so I'm not going to vote to close. – Adrian McCarthy Mar 19 '16 at 14:55

5 Answers5

21

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)

CoffeDeveloper
  • 7,961
  • 3
  • 35
  • 69
  • good, if you are confused I could refactor the code to make it more readable. – CoffeDeveloper Feb 16 '15 at 20:55
  • @Synthetic: Since you're on windows, have a look at [this](http://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter) and [that](https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx). The performance counter should provide you with very high precision (< 1us). – BDL Feb 17 '15 at 10:19
  • 2
    why need 1000000 times extra precision when the FPS has at most 2 decimal digits? – CoffeDeveloper Feb 17 '15 at 21:42
8

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;
}
McLovin
  • 3,295
  • 7
  • 32
  • 67
  • So I just now tried that, but it appears that delta_ticks never goes above 0? I made sure that my theory is correct by putting an exit(0) inside the if statement, and it never quit.(I ran it for about a minute.) – Xenonic Feb 15 '15 at 23:19
  • 1
    @Synthetic Maybe `clock()` is not precise enough? You should try `std::chrono::high_resolution_clock`. – HolyBlackCat Feb 15 '15 at 23:20
  • 1
    With APIs like OpenGL, where rendering happens asynchronously on the GPU, this will not measure the actual rendering time. – Reto Koradi Feb 15 '15 at 23:21
  • @HolyBlackCat I replaced the two clock() functions with your idea of std::chrono::... but a compile error comes up saying: Error: expected primary-expression before ';' token Error: expected primary-expression before '-' token. My code function looks like this now: `current_ticks = std::chrono::high_resolution_clock; delta_ticks = std::chrono::high_resolution_clock - current_ticks; if(delta_ticks > 0) { FPS = CLOCKS_PER_SEC / delta_ticks; exit(0); } std::cout << FPS;` – Xenonic Feb 15 '15 at 23:29
  • @HolyBlackCat Well, that will negatively affect the performance, so you would get a Heisenberg effect. Also, there are GPU vendors who don't finish rendering when you call `glFinish()`. – Reto Koradi Feb 15 '15 at 23:30
  • Oh crap, sorry that it's super hard to read the code!(Just look for the semicolons to determine a new line) – Xenonic Feb 15 '15 at 23:30
  • After running my program for even longer, the delta_ticks DOES go above 0, in fact, it was locking at 1000? This result was consistence after about 3 minutes of run time. – Xenonic Feb 15 '15 at 23:47
  • I tried the code I wrote. It works as expected. Try replacing `render()` with a `Sleep()` function in order to investigate how it works. – McLovin Feb 16 '15 at 05:45
  • @RetoKoradi I thought about it. In fact, that advice of mine was a mistake. OP don't need `glFinish()` here, because actual rendering time is not important in this case. I'll delete that comment. – HolyBlackCat Feb 16 '15 at 12:53
  • happy division by 0! glFinish will just send all commands to GPU. how long the GPU takes to process them is unknown, unless you use specific funcionality like timer querys! See my answer – CoffeDeveloper Feb 16 '15 at 15:09
  • @DarioOO Did you miss the if statement? – McLovin Feb 16 '15 at 15:36
  • YES :D apparently totally missed it – CoffeDeveloper Feb 16 '15 at 16:40
4

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;
    }
}
user_number153
  • 492
  • 4
  • 7
0

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
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 */