veloren/server/src/sys/metrics.rs
2021-03-27 18:24:10 +01:00

141 lines
4.5 KiB
Rust

use crate::{
metrics::{EcsSystemMetrics, PhysicsMetrics, TickMetrics},
HwStats, Tick, TickStart,
};
use common::{resources::TimeOfDay, terrain::TerrainGrid};
use common_ecs::{Job, Origin, Phase, SysMetrics, System};
use specs::{Entities, Join, Read, ReadExpect};
use std::time::Instant;
/// This system exports metrics
#[derive(Default)]
pub struct Sys;
impl<'a> System<'a> for Sys {
#[allow(clippy::type_complexity)]
type SystemData = (
Option<Entities<'a>>,
ReadExpect<'a, HwStats>,
ReadExpect<'a, Tick>,
ReadExpect<'a, TimeOfDay>,
ReadExpect<'a, TickStart>,
Option<Read<'a, TerrainGrid>>,
Read<'a, SysMetrics>,
Read<'a, common_ecs::PhysicsMetrics>,
ReadExpect<'a, EcsSystemMetrics>,
ReadExpect<'a, TickMetrics>,
ReadExpect<'a, PhysicsMetrics>,
);
const NAME: &'static str = "metrics";
const ORIGIN: Origin = Origin::Server;
const PHASE: Phase = Phase::Apply;
fn run(
_job: &mut Job<Self>,
(
entities,
hw_stats,
tick,
time_of_day,
tick_start,
terrain,
sys_metrics,
phys_metrics,
export_ecs,
export_tick,
export_physics,
): Self::SystemData,
) {
const NANOSEC_PER_SEC: f64 = std::time::Duration::from_secs(1).as_nanos() as f64;
let start = Instant::now();
let mut state = sys_metrics.stats.lock().unwrap();
//this system hasn't run yet
state.remove(Self::NAME);
for (name, stat) in common_ecs::gen_stats(
&state,
tick_start.0,
hw_stats.rayon_threads,
hw_stats.hardware_threads,
) {
export_ecs
.system_start_time
.with_label_values(&[&name])
.set(stat.start_ns() as i64);
export_ecs
.system_thread_avg
.with_label_values(&[&name])
.set(stat.avg_threads() as f64);
let len = stat.length_ns();
export_ecs
.system_length_time
.with_label_values(&[&name])
.set(len as i64);
export_ecs
.system_length_count
.with_label_values(&[&name])
.inc_by(len);
export_ecs
.system_length_hist
.with_label_values(&[&name])
.observe(len as f64 / NANOSEC_PER_SEC);
}
// Report other info
export_tick.time_of_day.set(time_of_day.0);
if tick.0.rem_euclid(100) == 0 {
if let Some(terrain) = terrain {
let mut chonk_cnt = 0;
let mut group_cnt = 0;
let chunk_cnt = terrain.iter().fold(0, |a, (_, c)| {
chonk_cnt += 1;
group_cnt += c.sub_chunk_groups();
a + c.sub_chunks_len()
});
export_tick.chonks_count.set(chonk_cnt as i64);
export_tick.chunks_count.set(chunk_cnt as i64);
export_tick.chunk_groups_count.set(group_cnt as i64);
}
if let Some(entities) = entities {
let entity_count = entities.join().count();
export_tick.entity_count.set(entity_count as i64);
common_base::plot!("entity count", entity_count as f64);
}
}
//detailed physics metrics
export_physics
.entity_entity_collision_checks_count
.inc_by(phys_metrics.entity_entity_collision_checks);
export_physics
.entity_entity_collisions_count
.inc_by(phys_metrics.entity_entity_collisions);
// export self time as best as possible
export_ecs
.system_start_time
.with_label_values(&["metrics"])
.set(start.duration_since(tick_start.0).as_nanos() as i64);
export_ecs
.system_thread_avg
.with_label_values(&["metrics"])
.set(1.0);
let len = start.elapsed().as_nanos() as u64;
export_ecs
.system_length_time
.with_label_values(&["metrics"])
.set(len as i64);
export_ecs
.system_length_count
.with_label_values(&["metrics"])
.inc_by(len);
export_ecs
.system_length_hist
.with_label_values(&["metrics"])
.observe(len as f64 / NANOSEC_PER_SEC);
}
}