mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add metrics for timing subsections of State::tick
This commit is contained in:
parent
2ad53aaa36
commit
87bf44241b
@ -1787,6 +1787,7 @@ impl Client {
|
|||||||
add_foreign_systems(dispatch_builder);
|
add_foreign_systems(dispatch_builder);
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
// TODO: avoid emitting these in the first place
|
// TODO: avoid emitting these in the first place
|
||||||
let _ = self
|
let _ = self
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#![feature(fundamental)]
|
|
||||||
|
|
||||||
pub mod userdata_dir;
|
pub mod userdata_dir;
|
||||||
|
|
||||||
pub use userdata_dir::userdata_dir;
|
pub use userdata_dir::userdata_dir;
|
||||||
|
@ -35,7 +35,7 @@ use specs::{
|
|||||||
storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage},
|
storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage},
|
||||||
Component, DispatcherBuilder, Entity as EcsEntity, WorldExt,
|
Component, DispatcherBuilder, Entity as EcsEntity, WorldExt,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::{sync::Arc, time::Instant};
|
||||||
use timer_queue::TimerQueue;
|
use timer_queue::TimerQueue;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -587,8 +587,19 @@ impl State {
|
|||||||
dt: Duration,
|
dt: Duration,
|
||||||
add_systems: impl Fn(&mut DispatcherBuilder),
|
add_systems: impl Fn(&mut DispatcherBuilder),
|
||||||
update_terrain_and_regions: bool,
|
update_terrain_and_regions: bool,
|
||||||
|
mut metrics: Option<&mut StateTickMetrics>,
|
||||||
) {
|
) {
|
||||||
span!(_guard, "tick", "State::tick");
|
span!(_guard, "tick", "State::tick");
|
||||||
|
|
||||||
|
// Timing code for server metrics
|
||||||
|
macro_rules! section_span {
|
||||||
|
($guard:ident, $label:literal) => {
|
||||||
|
span!(span_guard, $label);
|
||||||
|
let metrics_guard = metrics.as_mut().map(|m| MetricsGuard::new($label, m));
|
||||||
|
let $guard = (span_guard, metrics_guard);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Change the time accordingly.
|
// Change the time accordingly.
|
||||||
self.ecs.write_resource::<TimeOfDay>().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR;
|
self.ecs.write_resource::<TimeOfDay>().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR;
|
||||||
self.ecs.write_resource::<Time>().0 += dt.as_secs_f64();
|
self.ecs.write_resource::<Time>().0 += dt.as_secs_f64();
|
||||||
@ -602,7 +613,7 @@ impl State {
|
|||||||
self.update_region_map();
|
self.update_region_map();
|
||||||
}
|
}
|
||||||
|
|
||||||
span!(guard, "create dispatcher");
|
section_span!(guard, "create dispatcher");
|
||||||
// Run systems to update the world.
|
// Run systems to update the world.
|
||||||
// Create and run a dispatcher for ecs systems.
|
// Create and run a dispatcher for ecs systems.
|
||||||
let mut dispatch_builder =
|
let mut dispatch_builder =
|
||||||
@ -613,11 +624,11 @@ impl State {
|
|||||||
let mut dispatcher = dispatch_builder.build();
|
let mut dispatcher = dispatch_builder.build();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
||||||
span!(guard, "run systems");
|
section_span!(guard, "run systems");
|
||||||
dispatcher.dispatch(&self.ecs);
|
dispatcher.dispatch(&self.ecs);
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
||||||
span!(guard, "maintain ecs");
|
section_span!(guard, "maintain ecs");
|
||||||
self.ecs.maintain();
|
self.ecs.maintain();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
||||||
@ -626,7 +637,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process local events
|
// Process local events
|
||||||
span!(guard, "process local events");
|
section_span!(guard, "process local events");
|
||||||
|
|
||||||
let outcomes = self.ecs.read_resource::<EventBus<Outcome>>();
|
let outcomes = self.ecs.read_resource::<EventBus<Outcome>>();
|
||||||
let mut outcomes_emitter = outcomes.emitter();
|
let mut outcomes_emitter = outcomes.emitter();
|
||||||
@ -669,3 +680,40 @@ impl State {
|
|||||||
self.ecs.write_resource::<TerrainChanges>().clear();
|
self.ecs.write_resource::<TerrainChanges>().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Timing code for server metrics
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct StateTickMetrics {
|
||||||
|
pub timings: Vec<(&'static str, Duration)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StateTickMetrics {
|
||||||
|
fn add(&mut self, label: &'static str, dur: Duration) {
|
||||||
|
// Check for duplicates!
|
||||||
|
debug_assert!(
|
||||||
|
self.timings.iter().all(|(l, _)| *l != label),
|
||||||
|
"Duplicate label in state tick metrics {label}"
|
||||||
|
);
|
||||||
|
self.timings.push((label, dur));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MetricsGuard<'a> {
|
||||||
|
start: Instant,
|
||||||
|
label: &'static str,
|
||||||
|
metrics: &'a mut StateTickMetrics,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MetricsGuard<'a> {
|
||||||
|
fn new(label: &'static str, metrics: &'a mut StateTickMetrics) -> Self {
|
||||||
|
Self {
|
||||||
|
start: Instant::now(),
|
||||||
|
label,
|
||||||
|
metrics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for MetricsGuard<'_> {
|
||||||
|
fn drop(&mut self) { self.metrics.add(self.label, self.start.elapsed()); }
|
||||||
|
}
|
||||||
|
@ -80,6 +80,7 @@ mod tests {
|
|||||||
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
|
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ fn simple_run() {
|
|||||||
add_local_systems(dispatcher_builder);
|
add_local_systems(dispatcher_builder);
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ pub fn tick(state: &mut State, dt: Duration) {
|
|||||||
dispatch::<phys::Sys>(dispatch_builder, &[&character_behavior::Sys::sys_name()]);
|
dispatch::<phys::Sys>(dispatch_builder, &[&character_behavior::Sys::sys_name()]);
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,6 +684,7 @@ impl Server {
|
|||||||
// 4) Tick the server's LocalState.
|
// 4) Tick the server's LocalState.
|
||||||
// 5) Fetch any generated `TerrainChunk`s and insert them into the terrain.
|
// 5) Fetch any generated `TerrainChunk`s and insert them into the terrain.
|
||||||
// in sys/terrain.rs
|
// in sys/terrain.rs
|
||||||
|
let mut state_tick_metrics = Default::default();
|
||||||
self.state.tick(
|
self.state.tick(
|
||||||
dt,
|
dt,
|
||||||
|dispatcher_builder| {
|
|dispatcher_builder| {
|
||||||
@ -697,6 +698,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
Some(&mut state_tick_metrics),
|
||||||
);
|
);
|
||||||
|
|
||||||
let before_handle_events = Instant::now();
|
let before_handle_events = Instant::now();
|
||||||
@ -1002,6 +1004,12 @@ impl Server {
|
|||||||
.set((before_persistence_updates - before_entity_cleanup).as_nanos() as i64);
|
.set((before_persistence_updates - before_entity_cleanup).as_nanos() as i64);
|
||||||
tt.with_label_values(&["persistence_updates"])
|
tt.with_label_values(&["persistence_updates"])
|
||||||
.set((end_of_server_tick - before_persistence_updates).as_nanos() as i64);
|
.set((end_of_server_tick - before_persistence_updates).as_nanos() as i64);
|
||||||
|
for (label, duration) in state_tick_metrics.timings {
|
||||||
|
tick_metrics
|
||||||
|
.state_tick_time
|
||||||
|
.with_label_values(&[label])
|
||||||
|
.set(duration.as_nanos() as i64);
|
||||||
|
}
|
||||||
tick_metrics.tick_time_hist.observe(
|
tick_metrics.tick_time_hist.observe(
|
||||||
end_of_server_tick
|
end_of_server_tick
|
||||||
.duration_since(before_state_tick)
|
.duration_since(before_state_tick)
|
||||||
|
@ -57,6 +57,8 @@ pub struct TickMetrics {
|
|||||||
pub chunk_groups_count: IntGauge,
|
pub chunk_groups_count: IntGauge,
|
||||||
pub entity_count: IntGauge,
|
pub entity_count: IntGauge,
|
||||||
pub tick_time: IntGaugeVec,
|
pub tick_time: IntGaugeVec,
|
||||||
|
/// Timing of some subsections of `State::tick`.
|
||||||
|
pub state_tick_time: IntGaugeVec,
|
||||||
pub tick_time_hist: Histogram,
|
pub tick_time_hist: Histogram,
|
||||||
pub build_info: IntGauge,
|
pub build_info: IntGauge,
|
||||||
pub start_time: IntGauge,
|
pub start_time: IntGauge,
|
||||||
@ -349,6 +351,13 @@ impl TickMetrics {
|
|||||||
Opts::new("tick_time", "time in ns required for a tick of the server"),
|
Opts::new("tick_time", "time in ns required for a tick of the server"),
|
||||||
&["period"],
|
&["period"],
|
||||||
)?;
|
)?;
|
||||||
|
let state_tick_time = IntGaugeVec::new(
|
||||||
|
Opts::new(
|
||||||
|
"state_tick_time",
|
||||||
|
"time in ns for some subsections of State::tick",
|
||||||
|
),
|
||||||
|
&["period"],
|
||||||
|
)?;
|
||||||
// 33.33ms is the ideal tick time. So we have hight detail around it.
|
// 33.33ms is the ideal tick time. So we have hight detail around it.
|
||||||
// 300/700 are to detect high I/O blocks
|
// 300/700 are to detect high I/O blocks
|
||||||
let bucket = vec![
|
let bucket = vec![
|
||||||
@ -386,6 +395,7 @@ impl TickMetrics {
|
|||||||
registry.register(Box::new(time_of_day.clone()))?;
|
registry.register(Box::new(time_of_day.clone()))?;
|
||||||
registry.register(Box::new(light_count.clone()))?;
|
registry.register(Box::new(light_count.clone()))?;
|
||||||
registry.register(Box::new(tick_time.clone()))?;
|
registry.register(Box::new(tick_time.clone()))?;
|
||||||
|
registry.register(Box::new(state_tick_time.clone()))?;
|
||||||
registry.register(Box::new(tick_time_hist.clone()))?;
|
registry.register(Box::new(tick_time_hist.clone()))?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@ -394,6 +404,7 @@ impl TickMetrics {
|
|||||||
chunk_groups_count,
|
chunk_groups_count,
|
||||||
entity_count,
|
entity_count,
|
||||||
tick_time,
|
tick_time,
|
||||||
|
state_tick_time,
|
||||||
tick_time_hist,
|
tick_time_hist,
|
||||||
build_info,
|
build_info,
|
||||||
start_time,
|
start_time,
|
||||||
|
Loading…
Reference in New Issue
Block a user