mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
add min, max, stddev to stats
This commit is contained in:
parent
88721d4f7f
commit
4347cb4af2
@ -16,6 +16,13 @@ TimePoint now();
|
|||||||
/// Returns a sub-millisecond resolution duration between start and end.
|
/// Returns a sub-millisecond resolution duration between start and end.
|
||||||
Duration duration(const TimePoint& start, const TimePoint& end);
|
Duration duration(const TimePoint& start, const TimePoint& end);
|
||||||
|
|
||||||
|
struct Stats {
|
||||||
|
double mean;
|
||||||
|
double stddev;
|
||||||
|
double min;
|
||||||
|
double max;
|
||||||
|
};
|
||||||
|
|
||||||
/// Calculates and stores the moving average over K samples of execution time data
|
/// Calculates and stores the moving average over K samples of execution time data
|
||||||
/// for some single unit of code. Threadsafe.
|
/// for some single unit of code. Threadsafe.
|
||||||
struct UnitExecutionTime {
|
struct UnitExecutionTime {
|
||||||
@ -24,8 +31,9 @@ struct UnitExecutionTime {
|
|||||||
/// Adds a sample to the collection, overriding the oldest sample if needed.
|
/// Adds a sample to the collection, overriding the oldest sample if needed.
|
||||||
void add_sample(const Duration& dur);
|
void add_sample(const Duration& dur);
|
||||||
|
|
||||||
/// Calculates the average duration over the `measurement_count()` measurements.
|
/// Calculates the mean duration over the `measurement_count()` measurements,
|
||||||
Duration average_duration() const;
|
/// as well as the standard deviation.
|
||||||
|
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();
|
||||||
@ -39,14 +47,15 @@ struct UnitProfileCollection {
|
|||||||
/// Adds a sample to the collection, overriding the oldest sample if needed.
|
/// Adds a sample to the collection, overriding the oldest sample if needed.
|
||||||
void add_sample(const std::string& unit, const Duration& duration);
|
void add_sample(const std::string& unit, const Duration& duration);
|
||||||
|
|
||||||
/// Calculates the average duration over the `measurement_count()` measurements.
|
/// Calculates the mean duration over the `measurement_count()` measurements,
|
||||||
Duration average_duration(const std::string& unit);
|
/// as well as the standard deviation.
|
||||||
|
Stats stats(const std::string& unit);
|
||||||
|
|
||||||
/// 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(const std::string& unit);
|
size_t measurement_count(const std::string& unit);
|
||||||
|
|
||||||
/// Returns the averages for all stored units.
|
/// Returns the stats for all stored units.
|
||||||
std::unordered_map<std::string, double> all_average_durations();
|
std::unordered_map<std::string, Stats> all_stats();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::synchronized_value<std::unordered_map<std::string, UnitExecutionTime>> m_map;
|
boost::synchronized_value<std::unordered_map<std::string, UnitExecutionTime>> m_map;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Profiling.h"
|
#include "Profiling.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
prof::Duration prof::duration(const TimePoint& start, const TimePoint& end) {
|
prof::Duration prof::duration(const TimePoint& start, const TimePoint& end) {
|
||||||
return end - start;
|
return end - start;
|
||||||
@ -6,8 +7,8 @@ prof::Duration prof::duration(const TimePoint& start, const TimePoint& end) {
|
|||||||
prof::TimePoint prof::now() {
|
prof::TimePoint prof::now() {
|
||||||
return std::chrono::high_resolution_clock::now();
|
return std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
prof::Duration prof::UnitProfileCollection::average_duration(const std::string& unit) {
|
prof::Stats prof::UnitProfileCollection::stats(const std::string& unit) {
|
||||||
return m_map->operator[](unit).average_duration();
|
return m_map->operator[](unit).stats();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t prof::UnitProfileCollection::measurement_count(const std::string& unit) {
|
size_t prof::UnitProfileCollection::measurement_count(const std::string& unit) {
|
||||||
@ -22,13 +23,35 @@ size_t prof::UnitExecutionTime::measurement_count() {
|
|||||||
return m_measurements->size();
|
return m_measurements->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
prof::Duration prof::UnitExecutionTime::average_duration() const {
|
prof::Stats prof::UnitExecutionTime::stats() const {
|
||||||
|
Stats result {};
|
||||||
|
// calculate sum
|
||||||
auto measurements = m_measurements.synchronize();
|
auto measurements = m_measurements.synchronize();
|
||||||
|
if (measurements->size() == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.max = std::numeric_limits<double>::min();
|
||||||
|
result.min = std::numeric_limits<double>::max();
|
||||||
Duration sum {};
|
Duration sum {};
|
||||||
for (const auto& measurement : *measurements) {
|
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;
|
sum += measurement;
|
||||||
}
|
}
|
||||||
return sum / measurements->size();
|
// 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()));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prof::UnitExecutionTime::add_sample(const Duration& dur) {
|
void prof::UnitExecutionTime::add_sample(const Duration& dur) {
|
||||||
@ -39,12 +62,11 @@ prof::UnitExecutionTime::UnitExecutionTime()
|
|||||||
: m_measurements(boost::circular_buffer<Duration>(100)) {
|
: m_measurements(boost::circular_buffer<Duration>(100)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, double> prof::UnitProfileCollection::all_average_durations() {
|
std::unordered_map<std::string, prof::Stats> prof::UnitProfileCollection::all_stats() {
|
||||||
auto map = m_map.synchronize();
|
auto map = m_map.synchronize();
|
||||||
std::unordered_map<std::string, double> result {};
|
std::unordered_map<std::string, Stats> result {};
|
||||||
for (const auto& [name, time] : *map) {
|
for (const auto& [name, time] : *map) {
|
||||||
result[name] = time.average_duration().count();
|
result[name] = time.stats();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,9 +852,13 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
|
|||||||
UtilTable.set_function("DebugExecutionTime", [this]() -> sol::table {
|
UtilTable.set_function("DebugExecutionTime", [this]() -> sol::table {
|
||||||
sol::state_view StateView(mState);
|
sol::state_view StateView(mState);
|
||||||
sol::table Result = StateView.create_table();
|
sol::table Result = StateView.create_table();
|
||||||
auto durs = mProfile.all_average_durations();
|
auto stats = mProfile.all_stats();
|
||||||
for (const auto& [name, dur] : durs) {
|
for (const auto& [name, stat] : stats) {
|
||||||
Result[name] = dur;
|
Result[name] = StateView.create_table();
|
||||||
|
Result[name]["mean"] = stat.mean;
|
||||||
|
Result[name]["stddev"] = stat.stddev;
|
||||||
|
Result[name]["min"] = stat.min;
|
||||||
|
Result[name]["max"] = stat.max;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user