How do you calculate framerate in the form of a floating point?

I want to display the number of logic updates and rendered frames per second, both counters in floating point form. The logic is updated at a fixed interval (fixed number of steps per second), frames are rendered with or without VSync. Additionally, I want the status of these counters to be updated once or several times per second, depending on the settings (this may change at runtime).

My current solutions turned out to be unsatisfactory, so I need your advice. How do you calculate it? Please take into account the constant number of steps per second (currently 60ups) and any VSync state.

There are probably a dozen different ways.
Personally I think I would increment “size_t frameCount” every frame, and only update the output every 20-30 frames. Make sure you cast variables to floating point types at calculation time.

frameCount ++;
if(!(frameCount % 20))
{
    size_t thisTick = SDL_GetTicks();
   //  I wrote this in-editor so it's not tested.
    double fps = ((double)frameCount * 1000.0f) / ((double)(thisTick - lastTick)); 
    lastTick = thisTick;
    frameCount = 0;
   //update display of fps, I assume you know and use SDL_TTF?
}

With C++ you have std::to_string to get the double value into a string. Otherwise I think there’s the C function snprintf()

Another option is to instead use SDL_AddTimer to update the fps based on a time interval.

One of the silly things about monitoring FPS is that it slightly decreases your FPS doing the calculations and output. So if you just didn’t worry about FPS, you’d have a slightly faster game. However knowing when and where you might have reduced frame rates is critical information for a developer.

Oh, I almost forgot, here’s the lazyFoo Tutorial.

I currently have a much more sophisticated solution than you suggest, and I’m still not entirely happy with it. Maybe I’m picky or I don’t understand something. :wink:

I can’t just count frames because the more often I update the counter to display on screen, the less precision I will get. I think that it is better to calculate fps based on an array of samples and the accumulator, so that the result is sensibly averaged and has high precision.

I use sampling and accumulator for samples to calculate the time it takes to perform individual logic updates and the rendering (without flipping). I think that the topic of framerate should also be approached in this way.

I’m writing code in Free Pascal. But it doesn’t matter, no matter what language the examples are in (or even pseudo-language), I can translate them into Pascal without any problem. This is more about the algorithm itself, not the implementation, so feel free to use any syntax to illustrate your point of view. :wink:

This article shows how to refresh the counter every second, and the more often you refresh the counter, the more precision it loses.

The method I have above gives you the average over the previous 20 frames (sorry I did a lot of editing, I’m worried you saw it before this iteration)

So are you wanting to sample the frame-rate at a single frame, but only at predetermined intervals?
fps = 1000.0f / ((double)(SDL_GetTicks() - ticksAtFrameStart));

SDL3 now has a SDL_GetTicksNS() function that deals in the nano-second range, are you using SDL 2 or 3?

I haven’t used Pascal, so I’m not sure what limitations on precision might exist there…

I would like the framerate counter to be refreshed at fixed intervals, e.g. from once a second to ten times a second. By default it will be once per second, but I would like the player or me to be able to increase this frequency at runtime.

SDL2 has SDL_GetPerformanceCounter, which does the same thing. I use it e.g. to calculate how long a pure logic update takes — the result is nanosecond precision (actually down to 100-nanosecond ticks, because that’s what my PC supports), finally multiplied to get a high precision floating point number of milliseconds.

The framerate counter doesn’t have to be that precise, so it can be based on the number of milliseconds, but I would like it to be floating point and with reasonable precision.


Currently I have something like this to refresh updaterate and framerate counters:

// Calculate how much time has elapsed since the previous update of the frame rates.
TimeFramerateCurrent := Game_TimeGetTimeMilliseconds();
TimeFramerateElapsed := TimeFramerateCurrent - TimeFramerateLast;

// Update frame rate counters only if at least a second has elapsed.
if TimeFramerateElapsed >= 1000 then
begin
  // Calculate the average number of updates and rendered frames in the last second.
  UpdateNum := 1000.0 / TimeFramerateElapsed * InSecondUpdateNum;
  RenderNum := 1000.0 / TimeFramerateElapsed * InSecondRenderNum;

  // Set the time of the last update to the current time (more in one second, less in another).
  TimeFramerateLast := TimeFramerateCurrent;

  // Reset the counters and start counting activities again all the next second.
  InSecondUpdateNum := 0;
  InSecondRenderNum := 0;
end;

The result with VSync disabled is as follows:

updates: 21.93 | renders: 19.25
updates: 60.00 | renders: 60.00
updates: 60.00 | renders: 60.00
updates: 60.00 | renders: 60.00
updates: 60.00 | renders: 60.00
updates: 60.00 | renders: 60.00
updates: 60.00 | renders: 60.00

Excellent precision. I’m using FRAPS to check if my calculations are correct — it also shows 60 frames per second in the game window (but it uses integer counter).

Test with VSync on looks like this:

updates: 60.10 | renders: 59.11
updates: 60.16 | renders: 59.17
updates: 60.10 | renders: 59.11
updates: 60.16 | renders: 59.17
updates: 59.94 | renders: 58.94
updates: 59.94 | renders: 58.94
updates: 60.22 | renders: 59.23
updates: 60.10 | renders: 59.11
updates: 59.23 | renders: 59.23
updates: 60.22 | renders: 59.23
updates: 60.28 | renders: 59.29
updates: 60.00 | renders: 59.00
updates: 59.94 | renders: 58.94
updates: 60.46 | renders: 59.46
updates: 59.23 | renders: 59.23
updates: 60.10 | renders: 59.11

Looks very good — since my display apparently doesn’t have a perfect 60Hz refresh rate, in some seconds the logic updates 59 times, and some seconds it does 61 updates to catch up with what VSync loses — so sometimes it’s a little less than 60, and sometimes it’s a little more.

FRAPS seems to count frames in a special way, because it is able to update the counter (the one displayed in the game window) every frame — the value of the counter in the window increases smoothly, from 0 to 60, changing its value every frame. I’m curious how it does it.


What I have currently works quite sensibly, but I’m not very good at modifying the code into one that would maintain the current precision, but would be able to refresh the counter more often than once a second.

This increasing value from 0 to 60 actually gives a pretty good clue, they are not giving an at-the-moment frame-rate, but actually a moving average over time.
Count the amount of time that it takes to initially reach a stable value and that is likely their sample size.

Basically save a record of about 30 to 60 or so of your most recent fps calculations. Add all the samples together take the average and output the result.
Next frame: Add the newest fps sample, remove the oldest, report the average… And repeat.

This gives the appearance of a smoothly running machine even though there are peaks and dips over that time range. It gives the user a sense of security, and it is still “accurate enough” to what the performance of the program maintains per second.

I do think this is an excellent idea to program an FPS counter like this for your users so that they don’t feel like they have to question every single frame, why did that drop, what brought it back up, etc, but your original counter is more accurate from a developer standpoint to what is happening in the current frame.

Yeah, I already use this approach to calculate something else, so it shouldn’t be difficult to use it for framerate as well. However, I use eight samples to see any spikes. More than eight smoothed out the score too much. I’ll try this approach, I already have an idea of how it’s supposed to work.

I also use this for debugging. I need more precision than integer, but not too much. Basing on millisecond time and a few samples should be enough to slightly smooth the result. In release, I can always round the result to one decimal place or even to a whole integer, and use higher precision only for debugging.

I give up on calculating framerate more than once per second — it doesn’t make any sense. The very assumption of measuring an event multiple times for the purpose of only one measurement seems to be fundamentally wrong.

Especially since in my engine the measurement does not concern the number of iterations of the main loop, but the number of calls to the function updating the logic and rendering the frame. Updating game logic can be done multiple times within one iteration of the main loop, and the frame will only be rendered if the logic has been updated in the same iteration of the main loop.

Well, I’ll leave the update of the updaterate and framerate counters as they are, once per second, because it works great and provides reasonable precision, good for debugging and for players. However, refreshing counters containing the average time of a single update and rendering of a single frame will be subject to sampling, because there is always at least one sample per counter refresh. In fact, there is a minimum of 15 samples (refresh four times per second) and a maximum of 60 (refresh once per second).

Thanks for the discussion. :wink:

I’m back! :wink:

I finally came up with an idea and figured out how to implement it. It’s simpler than I expected. I implemented a test solution and it works perfectly, the framerate counters can be refreshed more often than once per second, and changing the framerate allows you to display changes smoothly, just like FRAPS does. Below is a description of how to implement it.

Samples as timestamps

If a given counter is to count the frequency of performing certain activities per second (e.g. logic updates, renders, etc.), but is to be refreshed more often than once per second, then they cannot be counted in the classic way, i.e. adding 1 to some accumulator. This is because if you multiply the accumulated number to get the overall number of activities per second, the precision of the result will be very poor.

Instead, you should collect timestamps, retrieved just after performing a given action. These timestamps should be added to a list/queue so as to accumulate them over an interval equal or greater than a second. Timestamps can be milliseconds (taken using the SDL_GetTicks64 function), or in the form of hardware counter ticks, if we want the highest precision (the SDL_GetPerformanceCounter function is used for this).

Millisecond timestamps are sufficient to create typical update counters and renders per second.

Calculating the result

Having filled the list with timestamps, you now need to calculate the final result from them. If the list is empty or contains only one item, the result is 0. This should be checked first to avoid dividing by 0 (more on this in a moment).

If there are more items, you need to get the value of the first and last item of the list and then calculate their difference — last - first. If the result is less than 1000, it means that not enough timestamps have been collected yet (the game runs for less than a second), so the result is simply the number of items in the list.

However, if the difference between the last and the first item is equal to or greater than 1000, the game runs for at least a second and additional calculations must be performed. You should remove all timestamps that are too old, i.e. those at the beginning of the list. Enough of them should be removed so that after deletion, the difference between the last and the first item on the list is not less than 1000. Finally, the number of list items is our framerate, in integer form.

To calculate framerate in floating-point form, you need to take into account not only the number of items, but also the period of time — and this period is the difference between the last and first timestamp of the list. Pseudocode calculating framerate in floating point form:

framerate = 1000.0 / (timestamp_last - timestamp_first) * timestamps_list.count;

The result will be an integer only if the difference of the last and first timestamp is perfectly 1000 — otherwise the result will be integer, e.g. 59.7. For debugging, it may be useful to round it to, for example, two decimal places, while for the player the result can be rounded to one decimal place or even to a whole integer.

Summary

The above allows you to calculate the number of actions performed per second, more often than once per second. In this way, you can display, for example, a framerate counter that will refresh its value, e.g. 5 times per second, and it will actually be possible to obtain 5 different values per second. If the framerate drops sharply (e.g. from 60fps to 20fps), the counter will show 5 different values in one second, gradually decreasing from ~60 to ~20.

Thanks to the solution proposed above, it is possible to refresh the framerate counter even in every frame of the game and this is the highest possible refresh rate of the counter. The lowest refresh rate is not specified — it could be once per 250ms, once per second, but could also be once per minute. However, it must be taken into account that the less often the counter is refreshed, the more timestamps will be added to the sample list, so the more memory the list will take up and the longer it will take to remove too old samples.

In my engine, I have specified that the range of available frequencies is from once per second (slowest) to ten times per second (fastest). More often it doesn’t make sense, it won’t be practical.

If I find time, I will try to provide complete pseudocode illustrating how to do the whole thing. The main loop in my engine is very complex and has a lot of features, so pasting its code into the post is pointless.