You can get the current framerate at any given moment using this formula:
framerate = (1 / gameTime.ElapsedGameTime.TotalSeconds);
Both of the other methods presented below give you a modified framerate, intended to be smoother, and have fewer fluctuations in the return value
This one works by weighting all previous frametimes on a logarithmic scale. I didn't like the idea of using an average to get a metric on game performance as framedrops aren't represented well (or at all if you have a high average) and very low/very high framerates have vastly different levels of accuracy if they are running on the same average.
To solve this, I made a SmartFramerate class (terrible name, I know)
class SmartFramerate
{
double currentFrametimes;
double weight;
int numerator;
public double framerate
{
get
{
return (numerator / currentFrametimes);
}
}
public SmartFramerate(int oldFrameWeight)
{
numerator = oldFrameWeight;
weight = (double)oldFrameWeight / ((double)oldFrameWeight - 1d);
}
public void Update(double timeSinceLastFrame)
{
currentFrametimes = currentFrametimes / weight;
currentFrametimes += timeSinceLastFrame;
}
}
You set the weight when you create the variable:
(a higher weight is more accurate to the instantaneous framerate, a lower weight is smoother. I find that 3-5 is a good balance)
SmartFramerate smartFPS = new SmartFramerate(5);
Call the Update method anywhere that will be run every frame:
smartFPS.Update(gameTime.ElapsedGameTime.TotalSeconds);
The current framerate may be accessed like so:
smartFPS.framerate
or printed like so:
debuginfo.Update("\n\nᴥ" + smartFPS.framerate.ToString("0000"), true);
(I'm putting it into a custom print class, so I apologize if the syntax looks funky)
However, if you wish to simply average a certain number of frames together, then this class is the most efficient way I have come up with to do so.
class SmoothFramerate
{
int samples;
int currentFrame;
double[] frametimes;
double currentFrametimes;
public double framerate
{
get
{
return (samples / currentFrametimes);
}
}
public SmoothFramerate(int Samples)
{
samples = Samples;
currentFrame = 0;
frametimes = new double[samples];
}
public void Update(double timeSinceLastFrame)
{
currentFrame++;
if (currentFrame >= frametimes.Length) { currentFrame = 0; }
currentFrametimes -= frametimes[currentFrame];
frametimes[currentFrame] = timeSinceLastFrame;
currentFrametimes += frametimes[currentFrame];
}
}
To use it, simply initialize a SmoothFramerate variable where ever you wish to use it, passing the amount of frames you want averaged:
SmoothFramerate smoothFPS = new SmoothFramerate(1000);
Update, access, and print the current framerate exactly as you would using the SmartFramerate class above.
Thanks for reading, I hope this helps someone out.