Initial commit: full project code
This commit is contained in:
204
common/include/common/metrics.hpp
Normal file
204
common/include/common/metrics.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#pragma once
|
||||
#include "types.hpp"
|
||||
#include "ring_buffer.hpp"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
|
||||
namespace netcode {
|
||||
|
||||
// Метрики позиции
|
||||
struct PositionMetrics {
|
||||
double mae = 0.0; // Mean Absolute Error
|
||||
double mse = 0.0; // Mean Squared Error
|
||||
double max_error = 0.0; // Максимальная ошибка
|
||||
uint32_t sample_count = 0;
|
||||
};
|
||||
|
||||
// Метрики сети
|
||||
struct NetworkMetrics {
|
||||
double rtt_ms = 0.0;
|
||||
double jitter_ms = 0.0;
|
||||
double packet_loss_percent = 0.0;
|
||||
uint64_t bytes_sent = 0;
|
||||
uint64_t bytes_received = 0;
|
||||
uint64_t packets_sent = 0;
|
||||
uint64_t packets_received = 0;
|
||||
};
|
||||
|
||||
// Метрики алгоритмов компенсации
|
||||
struct CompensationMetrics {
|
||||
uint32_t predictions_per_second = 0;
|
||||
uint32_t reconciliations_per_second = 0;
|
||||
double avg_correction_distance = 0.0;
|
||||
double max_correction_distance = 0.0;
|
||||
uint32_t rollbacks_count = 0;
|
||||
double input_delay_ms = 0.0;
|
||||
};
|
||||
|
||||
// Накопитель метрик
|
||||
class MetricsCollector {
|
||||
public:
|
||||
void add_position_error(float predicted_x, float predicted_y,
|
||||
float actual_x, float actual_y) {
|
||||
float dx = predicted_x - actual_x;
|
||||
float dy = predicted_y - actual_y;
|
||||
float error = std::sqrt(dx * dx + dy * dy);
|
||||
|
||||
position_errors_.push(error);
|
||||
total_error_ += error;
|
||||
total_squared_error_ += error * error;
|
||||
max_error_ = (std::max)(max_error_, static_cast<double>(error));
|
||||
error_count_++;
|
||||
}
|
||||
|
||||
void add_correction(float distance) {
|
||||
corrections_.push(distance);
|
||||
correction_count_++;
|
||||
total_correction_ += distance;
|
||||
max_correction_ = (std::max)(max_correction_, static_cast<double>(distance));
|
||||
}
|
||||
|
||||
void add_reconciliation() {
|
||||
reconciliation_count_++;
|
||||
}
|
||||
|
||||
void add_prediction() {
|
||||
prediction_count_++;
|
||||
}
|
||||
|
||||
void add_rollback() {
|
||||
rollback_count_++;
|
||||
}
|
||||
|
||||
PositionMetrics get_position_metrics() const {
|
||||
PositionMetrics m;
|
||||
m.sample_count = error_count_;
|
||||
if (error_count_ > 0) {
|
||||
m.mae = total_error_ / error_count_;
|
||||
m.mse = total_squared_error_ / error_count_;
|
||||
m.max_error = max_error_;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
CompensationMetrics get_compensation_metrics(double elapsed_seconds) const {
|
||||
CompensationMetrics m;
|
||||
if (elapsed_seconds > 0) {
|
||||
m.predictions_per_second = static_cast<uint32_t>(prediction_count_ / elapsed_seconds);
|
||||
m.reconciliations_per_second = static_cast<uint32_t>(reconciliation_count_ / elapsed_seconds);
|
||||
}
|
||||
if (correction_count_ > 0) {
|
||||
m.avg_correction_distance = total_correction_ / correction_count_;
|
||||
}
|
||||
m.max_correction_distance = max_correction_;
|
||||
m.rollbacks_count = rollback_count_;
|
||||
return m;
|
||||
}
|
||||
void reset_compensation_metrics() {
|
||||
prediction_count_ = 0;
|
||||
reconciliation_count_ = 0;
|
||||
total_correction_ = 0.0;
|
||||
max_correction_ = 0.0;
|
||||
correction_count_ = 0;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
position_errors_.clear();
|
||||
corrections_.clear();
|
||||
total_error_ = 0;
|
||||
total_squared_error_ = 0;
|
||||
max_error_ = 0;
|
||||
error_count_ = 0;
|
||||
total_correction_ = 0;
|
||||
max_correction_ = 0;
|
||||
correction_count_ = 0;
|
||||
prediction_count_ = 0;
|
||||
reconciliation_count_ = 0;
|
||||
rollback_count_ = 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
RingBuffer<float, 1024> position_errors_;
|
||||
RingBuffer<float, 256> corrections_;
|
||||
|
||||
double total_error_ = 0;
|
||||
double total_squared_error_ = 0;
|
||||
double max_error_ = 0;
|
||||
uint32_t error_count_ = 0;
|
||||
|
||||
double total_correction_ = 0;
|
||||
double max_correction_ = 0;
|
||||
uint32_t correction_count_ = 0;
|
||||
|
||||
uint32_t prediction_count_ = 0;
|
||||
uint32_t reconciliation_count_ = 0;
|
||||
uint32_t rollback_count_ = 0;
|
||||
};
|
||||
|
||||
|
||||
class MetricsLogger {
|
||||
public:
|
||||
explicit MetricsLogger(const std::string& filename = "client_metrics.csv") {
|
||||
file_.open(filename);
|
||||
if (file_.is_open()) {
|
||||
file_ << "timestamp_ms,preset,algorithm,rtt_ms,jitter_ms,packet_loss_percent,"
|
||||
<< "packets_sent_per_sec,packets_delivered_per_sec,packets_lost_per_sec,packets_duplicated_per_sec,"
|
||||
<< "fps,inputs_per_sec,snapshots_per_sec,"
|
||||
<< "position_mae,position_mse,position_max_error,samples,"
|
||||
<< "predictions_per_sec,reconciliations_per_sec,"
|
||||
<< "avg_correction_distance,max_correction_distance\n";
|
||||
file_.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void log(uint64_t timestamp_ms,
|
||||
const std::string& preset_name,
|
||||
const std::string& algorithm_name,
|
||||
double rtt_ms,
|
||||
double jitter_ms,
|
||||
double packet_loss_percent,
|
||||
uint64_t packets_sent_ps,
|
||||
uint64_t packets_delivered_ps,
|
||||
uint64_t packets_lost_ps,
|
||||
uint64_t packets_duplicated_ps,
|
||||
float fps,
|
||||
uint32_t inputs_per_sec,
|
||||
uint32_t snapshots_per_sec,
|
||||
const PositionMetrics& pos,
|
||||
const CompensationMetrics& comp) {
|
||||
if (!file_.is_open()) return;
|
||||
|
||||
file_ << timestamp_ms << ","
|
||||
<< preset_name << ","
|
||||
<< algorithm_name << ","
|
||||
<< std::fixed << std::setprecision(3)
|
||||
<< rtt_ms << ","
|
||||
<< jitter_ms << ","
|
||||
<< packet_loss_percent << ","
|
||||
<< packets_sent_ps << ","
|
||||
<< packets_delivered_ps << ","
|
||||
<< packets_lost_ps << ","
|
||||
<< packets_duplicated_ps << ","
|
||||
<< fps << ","
|
||||
<< inputs_per_sec << ","
|
||||
<< snapshots_per_sec << ","
|
||||
<< pos.mae << ","
|
||||
<< pos.mse << ","
|
||||
<< pos.max_error << ","
|
||||
<< pos.sample_count << ","
|
||||
<< comp.predictions_per_second << ","
|
||||
<< comp.reconciliations_per_second << ","
|
||||
<< comp.avg_correction_distance << ","
|
||||
<< comp.max_correction_distance << "\n";
|
||||
file_.flush();
|
||||
}
|
||||
|
||||
private:
|
||||
std::ofstream file_;
|
||||
};
|
||||
|
||||
} // namespace netcode
|
||||
Reference in New Issue
Block a user