Using the Moving Average Filter for Profiling Stats
When displaying profiling stats or FPS counters or whatever value that varies a lot frame to frame, you don’t want to show the real values since they can vary too much and make the stats unreadable.
Displaying an average over a certain period of time is a good idea. But how to compute that average?
Simple Moving Average
A common solution is to keep the n last values, and then compute the average of these n values to display. This is called a simple moving average and is computed like this:
tFloat MeanValue = 0.0f; for(tU32 i=0; i<n; i++) MeanValue += RecentValues[i]; MeanValue /= n;
It works fine in some scenarios, like displaying a FPS counter. On the other hand, it’s not very appropriate when a lot of values needs to be computed, like for profiling stats, as the amount of data can become too large and the time spent updating the values can become too high.
Exponential Moving Average
Another solution that I’ve been using for years now is the exponential moving average. Essentially, it’s moving the current mean value toward the actual value every iteration, by a certain percentage. It’s computed like this:
MeanValue = MeanValue * 0.99f + CurrentValue * 0.01f;
The advantage of this solution is that you don’t need to keep the n last values, as opposed to the simple moving average.
Here’s a graph comparing the two solutions:
As you can see at the beginning of the graph, the EMA takes some time to react to big changes. This is easily fixed by initializing the mean value to the first value, but wasn’t done here to show how it reacts to big changes in the source data.
Compared to the SMA, the EMA is closer to the real averaged value, has less variations and takes less memory and CPU, which makes it a good function to compute and display averaged values in a profiling system.