|
|
|
|
|
by mightyham
55 days ago
|
|
If all you care about is a windowed average you can implement the fps counter (really you keep track of seconds per frame) using an exponential moving average which has constant time and space complexity regardless of window size. The calculation you do once a frame is: spf_avg = alpha * cur_spf + (1.0f - alpha) * spf_avg; For alpha value you can use the formula: alpha = 2/(n+1) Which will give smoothing comparable to an n sample moving average. This is the same formula used for n-day exponential moving averages for stocks. As the article points out, this is a sample based window which is not as good as a time based window, but it's also dead simple to implement. Edit: Just spit balling because I haven't thought about this problem in a while and asked AI to give a foruma for EMA with variable duration events, so take it with a grain of salt. Maybe for a time based window you could use a dynamic alpha (forgetting factor) with the following formula: alpha = 1-e^-(cur_spf/window_secs) |
|
So...T seconds have elapsed since your last frame, and you have a new data point you'd like to incorporate into your EMA (and, for this problem, that data point is T itself). You keep e^-(bT) of the old data, 1 minus that of the new data, and you're done. Alpha is indeed 1-e^-(b * cur_spf) for some constant b, just like the AI said.
Which b do you choose though? I usually prefer to think of it in terms of half lives. Let H be your desired half life, and set 1-e^-(bH) equal to 1/2. You get b=log(2)/H. That's similar to the AI answer, but it rescales window_secs into a parameter you can actually start to reason about. The AI answer gives you a 1/e life instead, which is a less comfortable constant to mentally process.
That answer also naturally generalizes to other "time" axes or denominators. Suppose you want to EMA using discrete events rather than wall-clock time. Replace T in your dynamic alpha with the discrete count of events you haven't updated the EMA with yet (e.g., if something happens every time tick you would usually take T=1, but you can increase that based on a few skipped frames or whatever if you'd like).
As a fun fact, you can tailor this sort of stateless solution to have almost any decay property you'd like. Start with your favorite ODE satisfying a few properties, and this equation falls out as the step a discrete solver would take to approximate the ODE.