mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-02-16 02:30:54 +00:00
switch to a runnning calculation for stdev and mean
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include <boost/thread/synchronized_value.hpp>
|
#include <boost/thread/synchronized_value.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace prof {
|
namespace prof {
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ Duration duration(const TimePoint& start, const TimePoint& end);
|
|||||||
|
|
||||||
struct Stats {
|
struct Stats {
|
||||||
double mean;
|
double mean;
|
||||||
double stddev;
|
double stdev;
|
||||||
double min;
|
double min;
|
||||||
double max;
|
double max;
|
||||||
size_t n;
|
size_t n;
|
||||||
@@ -38,11 +39,15 @@ struct UnitExecutionTime {
|
|||||||
Stats stats() const;
|
Stats stats() const;
|
||||||
|
|
||||||
/// Returns the number of elements the moving average is calculated over.
|
/// Returns the number of elements the moving average is calculated over.
|
||||||
size_t measurement_count();
|
size_t measurement_count() const { return m_total_calls; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::synchronized_value<boost::circular_buffer<Duration>> m_measurements;
|
|
||||||
size_t m_total_calls {};
|
size_t m_total_calls {};
|
||||||
|
double m_sum {};
|
||||||
|
// sum of measurements squared (for running stdev)
|
||||||
|
double m_measurement_sqr_sum {};
|
||||||
|
double m_min { std::numeric_limits<double>::max() };
|
||||||
|
double m_max { std::numeric_limits<double>::min() };
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Holds profiles for multiple units by name. Threadsafe.
|
/// Holds profiles for multiple units by name. Threadsafe.
|
||||||
|
|||||||
@@ -19,50 +19,28 @@ void prof::UnitProfileCollection::add_sample(const std::string& unit, const Dura
|
|||||||
m_map->operator[](unit).add_sample(duration);
|
m_map->operator[](unit).add_sample(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t prof::UnitExecutionTime::measurement_count() {
|
|
||||||
return m_measurements->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
prof::Stats prof::UnitExecutionTime::stats() const {
|
prof::Stats prof::UnitExecutionTime::stats() const {
|
||||||
Stats result {};
|
Stats result {};
|
||||||
// calculate sum
|
// calculate sum
|
||||||
auto measurements = m_measurements.synchronize();
|
result.n = m_total_calls;
|
||||||
if (measurements->size() == 0) {
|
result.max = m_min;
|
||||||
return result;
|
result.min = m_max;
|
||||||
}
|
// calculate mean: mean = sum_x / n
|
||||||
result.n = measurements->size();
|
result.mean = m_sum / double(m_total_calls);
|
||||||
result.max = std::numeric_limits<double>::min();
|
// calculate stdev: stdev = sqrt((sum_x2 / n) - (mean * mean))
|
||||||
result.min = std::numeric_limits<double>::max();
|
result.stdev = std::sqrt((m_measurement_sqr_sum / double(result.n)) - (result.mean * result.mean));
|
||||||
Duration sum {};
|
|
||||||
for (const auto& measurement : *measurements) {
|
|
||||||
if (measurement.count() > result.max) {
|
|
||||||
result.max = measurement.count();
|
|
||||||
}
|
|
||||||
if (measurement.count() < result.min) {
|
|
||||||
result.min = measurement.count();
|
|
||||||
}
|
|
||||||
sum += measurement;
|
|
||||||
}
|
|
||||||
// calculate mean
|
|
||||||
result.mean = (sum / measurements->size()).count();
|
|
||||||
// calculate stddev
|
|
||||||
result.stddev = 0;
|
|
||||||
for (const auto& measurement : *measurements) {
|
|
||||||
// (measurements[i] - mean)^2
|
|
||||||
result.stddev += std::pow(measurement.count() - result.mean, 2);
|
|
||||||
}
|
|
||||||
result.stddev = std::sqrt(result.stddev / double(measurements->size()));
|
|
||||||
result.total_calls = m_total_calls;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prof::UnitExecutionTime::add_sample(const Duration& dur) {
|
void prof::UnitExecutionTime::add_sample(const Duration& dur) {
|
||||||
m_measurements->push_back(dur);
|
m_sum += dur.count();
|
||||||
|
m_measurement_sqr_sum += dur.count() * dur.count();
|
||||||
|
m_min = std::min(dur.count(), m_min);
|
||||||
|
m_max = std::max(dur.count(), m_max);
|
||||||
++m_total_calls;
|
++m_total_calls;
|
||||||
}
|
}
|
||||||
|
|
||||||
prof::UnitExecutionTime::UnitExecutionTime()
|
prof::UnitExecutionTime::UnitExecutionTime() {
|
||||||
: m_measurements(boost::circular_buffer<Duration>(100)) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, prof::Stats> prof::UnitProfileCollection::all_stats() {
|
std::unordered_map<std::string, prof::Stats> prof::UnitProfileCollection::all_stats() {
|
||||||
|
|||||||
@@ -856,7 +856,7 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
|
|||||||
for (const auto& [name, stat] : stats) {
|
for (const auto& [name, stat] : stats) {
|
||||||
Result[name] = StateView.create_table();
|
Result[name] = StateView.create_table();
|
||||||
Result[name]["mean"] = stat.mean;
|
Result[name]["mean"] = stat.mean;
|
||||||
Result[name]["stddev"] = stat.stddev;
|
Result[name]["stdev"] = stat.stdev;
|
||||||
Result[name]["min"] = stat.min;
|
Result[name]["min"] = stat.min;
|
||||||
Result[name]["max"] = stat.max;
|
Result[name]["max"] = stat.max;
|
||||||
Result[name]["n"] = stat.n;
|
Result[name]["n"] = stat.n;
|
||||||
|
|||||||
15
src/main.cpp
15
src/main.cpp
@@ -20,6 +20,7 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Http.h"
|
#include "Http.h"
|
||||||
#include "LuaAPI.h"
|
#include "LuaAPI.h"
|
||||||
|
#include "Profiling.h"
|
||||||
#include "SignalHandling.h"
|
#include "SignalHandling.h"
|
||||||
#include "TConfig.h"
|
#include "TConfig.h"
|
||||||
#include "THeartbeatThread.h"
|
#include "THeartbeatThread.h"
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
#include "TResourceManager.h"
|
#include "TResourceManager.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -124,7 +126,7 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TConfig Config(ConfigPath);
|
TConfig Config(ConfigPath);
|
||||||
|
|
||||||
if (Config.Failed()) {
|
if (Config.Failed()) {
|
||||||
@@ -176,6 +178,17 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
Http::Server::THttpServerInstance HttpServerInstance {};
|
Http::Server::THttpServerInstance HttpServerInstance {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prof::UnitExecutionTime t {};
|
||||||
|
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||||
|
t.add_sample(std::chrono::seconds(1));
|
||||||
|
t.add_sample(std::chrono::seconds(2));
|
||||||
|
t.add_sample(std::chrono::seconds(3));
|
||||||
|
}
|
||||||
|
auto stats = t.stats();
|
||||||
|
beammp_errorf("mean: {}, stdev: {}, min: {}, max: {}, n: {}", stats.mean, stats.stdev, stats.min, stats.max, stats.n);
|
||||||
|
|
||||||
|
exit(69);
|
||||||
|
|
||||||
Application::SetSubsystemStatus("Main", Application::Status::Good);
|
Application::SetSubsystemStatus("Main", Application::Status::Good);
|
||||||
RegisterThread("Main(Waiting)");
|
RegisterThread("Main(Waiting)");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user