Make sampling period of fps_metrics configurable
Hi, it would be nice if the sampling period of fps_metrics would be configurable, like the regular fps one is. I personally find the default way to high and would like to change it without compiling a custom version.
Having it based on ms like in the fps would be the nicest, but I think making size_t max_size in fps_metrics.h configurable would be enough
So, std::vector<float> frametimes would store 10 (etc...) seconds worth of frametimes instead of 10.000 frames?
https://github.com/flightlessmango/MangoHud/blob/0c11540e68a8ddec9944faa2707f1ed669976a47/src/fps_metrics.h#L21-L23C9
I think it would be good enough if just the number of frames would be configurable (like 500 instead of 10.000 frames)
Having it based on ms like in the fps would be the nicest
so this no longer applies?
If this is easy enough to implement it would be nice, but it would be fine without
I don't see any problems implementing either of those approaches.
But storing some amount of seconds worth of frametimes is definitely better approach, because you have a constant amount of time by which you divide your frametimes.
If one user has 60fps, and other has 150fps, mangohud will show avg fps over 2.8 minutes for first user, while for other only over 1.1 minute (in case max_size=10000)
Ok sorry for wasting your time on those replies then. That sounds great
You're not, I'm just trying to better understand what functionality you want.
We used to collect fps metrics over a set time frame, but that had issues, which is why I changed it. For example long frames hold more weight than other frames, so the calculations become less accurate
So you're saying that I would be just returning the old method?
And adding configurable max_size is enough here?
The main problem here is misunderstanding what AVG metric does.
The point of AVG metric is to show average fps value over some time frame.
sum_of_fps_over_30sec / 30sec is mathematically correct here. But humans will think that number is wrong, even though it fulfills it's purpose.
IMO, people think that avg fps is some kind of game smoothess indicator, when it's not, so no need to butcher it up in code and still call it avg fps
Currently what mangohud calls avg fps is arithmetic mean of frame times or harmonic mean of fps
For example long frames hold more weight than other frames, so the calculations become less accurate
For that, median fps is needed, to not get affected by any outliers
I thought about it myself a little. Isn't that solvable by dynamically changing the max_size based on the fps (f/s*s=f)? That keeps all frames equally weight and gives seconds as an input.
instant change:
diff --git a/src/fps_metrics.h b/src/fps_metrics.h
index d755c91..3a32998 100644
--- a/src/fps_metrics.h
+++ b/src/fps_metrics.h
@@ -129,8 +129,9 @@ class fpsMetrics {
// lock before modifying vector
std::lock_guard<std::mutex> lock(mtx);
-
- if (frametimes.size() >= max_size)
+ max_size = 1 * fps;
+ SPDLOG_INFO("FPS: {}, Max Size: {}, Frametime Size: {}", fps, max_size, frametimes.size());
+ while (frametimes.size() >= max_size)
frametimes.erase(frametimes.begin());
frametimes.push_back(new_frametime);
ramp up/ ramp down
diff --git a/src/fps_metrics.h b/src/fps_metrics.h
index d755c91..ddd4ae5 100644
--- a/src/fps_metrics.h
+++ b/src/fps_metrics.h
@@ -129,10 +129,13 @@ class fpsMetrics {
// lock before modifying vector
std::lock_guard<std::mutex> lock(mtx);
-
- if (frametimes.size() >= max_size)
+ max_size = 1 * fps;
+ SPDLOG_INFO("FPS: {}, Max Size: {}, Frametime Size: {}", fps, max_size, frametimes.size());
+ if (frametimes.size() >= max_size) {
frametimes.erase(frametimes.begin());
-
+ if (frametimes.size() >= max_size)
+ frametimes.erase(frametimes.begin());
+ }
frametimes.push_back(new_frametime);
}
These would both be with a one second sampling period (I've never done anything in anything lower level than python, so I don't trust that code being proper and don't trust myself with making it configurable without making it a vibe coded mess )
actually it would be way smarter to base it of the already calculated avg fps. But that goes beyond my C++ skills
Isn't that solvable by dynamically changing the max_size based on the fps (f/s*s=f)?
f/s*s=f this line just states that f = f
did you mean max_size = sec * avg_fps?
Yes It's the same thing but with the units