Skip to content

Instantly share code, notes, and snippets.

@happyme531
Created September 6, 2023 06:48
Show Gist options
  • Select an option

  • Save happyme531/3dba11f3c53006aa1817f0a89aceb5fe to your computer and use it in GitHub Desktop.

Select an option

Save happyme531/3dba11f3c53006aa1817f0a89aceb5fe to your computer and use it in GitHub Desktop.
Handy FPS or whatever counter class
// Author: hallo1, 2023-09-06
// Description: Simple FPS or whatever counter
#pragma once
#include <chrono>
#include <iostream>
#include <string>
class FPSCounter {
private:
float avgMsPerFrame = 0;
float varMsPerFrame = 0;
int currentSampleCount = 0;
std::chrono::time_point<std::chrono::steady_clock> lastTime =
std::chrono::steady_clock::now();
std::chrono::milliseconds logInterval = std::chrono::milliseconds(1000);
std::chrono::time_point<std::chrono::steady_clock> lastLog =
std::chrono::steady_clock::now();
std::ostream &out;
std::string name;
public:
FPSCounter(
std::string name = "FPS",
std::chrono::milliseconds logInterval = std::chrono::milliseconds(1000),
std::ostream &out = std::cout)
: name(name), logInterval(logInterval), out(out) {}
void start() { lastTime = std::chrono::steady_clock::now(); }
void end() {
auto now = std::chrono::steady_clock::now();
auto ms =
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastTime)
.count();
currentSampleCount++;
avgMsPerFrame += (ms - avgMsPerFrame) / currentSampleCount;
// Welford's algorithm
varMsPerFrame = (varMsPerFrame * (currentSampleCount - 1) +
(ms - avgMsPerFrame) * (ms - avgMsPerFrame)) /
currentSampleCount;
auto intervalMs =
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastLog)
.count();
if (intervalMs > logInterval.count()) {
// Sampling itps, calculated by the number of samples divided by the time
float sampling_itps =
(float)currentSampleCount /
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastLog)
.count() *
1000;
// Timing itps, calculated by the average time per iteration
float timing_itps = 1000.0 / avgMsPerFrame;
float proportionPercentage = sampling_itps / timing_itps * 100;
out << std::setprecision(2) << std::fixed;
out << name << ": itps=" << sampling_itps
<< ", timing_itps=" << timing_itps << ", avg=" << avgMsPerFrame
<< "ms, stddev=" << sqrt(varMsPerFrame)
<< "ms, proportion=" << proportionPercentage
<< "%, samples=" << currentSampleCount << std::endl;
avgMsPerFrame = 0;
varMsPerFrame = 0;
currentSampleCount = 0;
lastLog = now;
}
}
};
// int main() {
// FPSCounter counter("test", std::chrono::milliseconds(1000));
// std::random_device rd;
// std::mt19937 gen(rd());
// std::normal_distribution<> d1(30, 5);
// std::normal_distribution<> d2(60, 5);
// while (true) {
// counter.start();
// //Some stressful work
// std::this_thread::sleep_for(std::chrono::milliseconds((int)d1(gen)));
// counter.end();
// //Maybe some other work
// std::this_thread::sleep_for(std::chrono::milliseconds((int)d2(gen)));
// }
// }
// test: itps=10.16, timing_itps=25.82, avg=38.73ms, stddev=8.85ms, proportion=39.34%, samples=11
// test: itps=9.62, timing_itps=28.99, avg=34.50ms, stddev=5.75ms, proportion=33.17%, samples=10
// test: itps=10.24, timing_itps=30.05, avg=33.27ms, stddev=5.20ms, proportion=34.08%, samples=11
// test: itps=9.68, timing_itps=28.82, avg=34.70ms, stddev=5.58ms, proportion=33.59%, samples=10
// test: itps=9.77, timing_itps=29.24, avg=34.20ms, stddev=5.99ms, proportion=33.40%, samples=10
// test: itps=8.84, timing_itps=25.35, avg=39.44ms, stddev=7.06ms, proportion=34.87%, samples=9
// test: itps=9.35, timing_itps=25.71, avg=38.90ms, stddev=6.55ms, proportion=36.36%, samples=10
// test: itps=9.70, timing_itps=29.15, avg=34.30ms, stddev=5.84ms, proportion=33.27%, samples=10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment