From c515fece28c67fa790f7f7c20903e805da09a749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Thu, 4 Mar 2021 15:00:16 +0100 Subject: [PATCH 1/5] Implement a VSystem trait that can be implemented by Systems. It will autodo some things, like track start and time and export those in system metrics Add a origin and implement it for all Systems in Veloren --- Cargo.lock | 12 +- common/Cargo.toml | 1 + common/src/lib.rs | 1 + common/src/metrics.rs | 7 +- common/src/vsystem.rs | 458 +++++++++++++++++++++++++ common/sys/src/aura.rs | 14 +- common/sys/src/beam.rs | 14 +- common/sys/src/buff.rs | 12 +- common/sys/src/character_behavior.rs | 16 +- common/sys/src/controller.rs | 14 +- common/sys/src/lib.rs | 40 +-- common/sys/src/melee.rs | 14 +- common/sys/src/mount.rs | 14 +- common/sys/src/phys.rs | 17 +- common/sys/src/projectile.rs | 17 +- common/sys/src/shockwave.rs | 17 +- common/sys/src/stats.rs | 16 +- server/src/lib.rs | 42 ++- server/src/metrics.rs | 34 +- server/src/rtsim/load_chunks.rs | 16 +- server/src/rtsim/mod.rs | 14 +- server/src/rtsim/tick.rs | 12 +- server/src/rtsim/unload_chunks.rs | 12 +- server/src/sys/agent.rs | 16 +- server/src/sys/entity_sync.rs | 14 +- server/src/sys/invite_timeout.rs | 14 +- server/src/sys/mod.rs | 34 +- server/src/sys/msg/character_screen.rs | 14 +- server/src/sys/msg/general.rs | 14 +- server/src/sys/msg/in_game.rs | 14 +- server/src/sys/msg/ping.rs | 14 +- server/src/sys/object.rs | 15 +- server/src/sys/persistence.rs | 14 +- server/src/sys/sentinel.rs | 16 +- server/src/sys/subscription.rs | 15 +- server/src/sys/terrain.rs | 14 +- server/src/sys/terrain_sync.rs | 18 +- server/src/sys/waypoint.rs | 14 +- voxygen/src/ecs/sys.rs | 11 +- voxygen/src/ecs/sys/floater.rs | 12 +- voxygen/src/ecs/sys/interpolation.rs | 12 +- 41 files changed, 871 insertions(+), 218 deletions(-) create mode 100644 common/src/vsystem.rs diff --git a/Cargo.lock b/Cargo.lock index 5cff08740c..8133a96275 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1643,6 +1643,15 @@ dependencies = [ "miniz_oxide 0.4.3", ] +[[package]] +name = "float-cmp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" +dependencies = [ + "num-traits", +] + [[package]] name = "fnv" version = "1.0.7" @@ -5598,6 +5607,7 @@ dependencies = [ "directories-next", "dot_vox", "enum-iterator", + "float-cmp", "hashbrown 0.9.1", "image", "indexmap", @@ -6681,4 +6691,4 @@ dependencies = [ name = "xml-rs" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" \ No newline at end of file diff --git a/common/Cargo.toml b/common/Cargo.toml index 7c5cb4c482..2d614c40a3 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -68,6 +68,7 @@ specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "9fab7b3 [dev-dependencies] #bench criterion = "0.3" +float-cmp = "0.8.0" [[bench]] name = "chonk_benchmark" diff --git a/common/src/lib.rs b/common/src/lib.rs index 472cd38b64..c3e8501488 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -71,6 +71,7 @@ pub mod uid; #[cfg(not(target_arch = "wasm32"))] pub mod vol; #[cfg(not(target_arch = "wasm32"))] pub mod volumes; +pub mod vsystem; pub use combat::DamageSource; #[cfg(not(target_arch = "wasm32"))] diff --git a/common/src/metrics.rs b/common/src/metrics.rs index cc7435bd41..58ebf31627 100644 --- a/common/src/metrics.rs +++ b/common/src/metrics.rs @@ -1,7 +1,12 @@ -use std::sync::atomic::AtomicU64; +use crate::vsystem::CpuTimeline; +use std::{ + collections::HashMap, + sync::{atomic::AtomicU64, Mutex}, +}; #[derive(Default)] pub struct SysMetrics { + pub stats: Mutex>, pub agent_ns: AtomicU64, pub mount_ns: AtomicU64, pub controller_ns: AtomicU64, diff --git a/common/src/vsystem.rs b/common/src/vsystem.rs new file mode 100644 index 0000000000..b1af1ee844 --- /dev/null +++ b/common/src/vsystem.rs @@ -0,0 +1,458 @@ +use crate::metrics::SysMetrics; +use specs::{ReadExpect, RunNow, System}; +use std::{collections::HashMap, time::Instant}; + +/// measuring the level of threads a unit of code ran on. Use Rayon when it ran +/// on their threadpool. Use Exact when you know on how many threads your code +/// ran on exactly. +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum ParMode { + None, /* Job is not running at all */ + Single, + Rayon, + Exact(u16), +} + +//TODO: make use of the phase of a system for advanced scheduling and logging +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Phase { + Create, + Review, + Apply, +} + +//TODO: make use of the origin of the system for better logging +#[derive(Clone, PartialEq, Debug)] +pub enum Origin { + Common, + Client, + Server, + Frontend(&'static str), +} + +#[derive(Default, Debug, Clone)] +pub struct CpuTimeline { + /// + /// - The first entry will always be ParMode::Single, as when the + /// System::run is executed, we run + /// single threaded until we start a Rayon::ParIter or similar + /// - The last entry will contain the end time of the System. To mark the + /// End it will always contain + /// ParMode::None, which means from that point on 0 CPU threads work in this + /// system + measures: Vec<(Instant, ParMode)>, +} + +#[derive(Default)] +pub struct CpuTimeStats { + /// the first entry will always be 0, the last entry will always be `dt` + /// `usage` starting from `ns` + measures: Vec<(/* ns */ u64, /* usage */ f32)>, +} + +/// Parallel Mode tells us how much you are scaling. `None` means your code +/// isn't running. `Single` means you are running single threaded. +/// `Rayon` means you are running on the rayon threadpool. +impl ParMode { + fn threads(&self, rayon_threads: u16) -> u16 { + match self { + ParMode::None => 0, + ParMode::Single => 1, + ParMode::Rayon => rayon_threads, + ParMode::Exact(u) => *u, + } + } +} + +impl CpuTimeline { + fn reset(&mut self) { + self.measures.clear(); + self.measures.push((Instant::now(), ParMode::Single)); + } + + /// Start a new measurement. par will be covering the parallelisation AFTER + /// this statement, till the next / end of the VSystem. + pub fn measure(&mut self, par: ParMode) { self.measures.push((Instant::now(), par)); } + + fn end(&mut self) { self.measures.push((Instant::now(), ParMode::None)); } + + fn get(&self, time: Instant) -> ParMode { + match self.measures.binary_search_by_key(&time, |&(a, _)| a) { + Ok(id) => self.measures[id].1, + Err(0) => ParMode::None, /* not yet started */ + Err(id) => self.measures[id - 1].1, + } + } +} + +impl CpuTimeStats { + pub fn length_ns(&self) -> u64 { self.end_ns() - self.start_ns() } + + pub fn start_ns(&self) -> u64 { + self.measures + .iter() + .find(|e| e.1 > 0.001) + .unwrap_or(&(0, 0.0)) + .0 + } + + pub fn end_ns(&self) -> u64 { self.measures.last().unwrap_or(&(0, 0.0)).0 } + + pub fn avg_threads(&self) -> f32 { + let mut sum = 0.0; + for w in self.measures.windows(2) { + let len = w[1].0 - w[0].0; + let h = w[0].1; + sum += len as f32 * h; + } + sum / (self.length_ns() as f32) + } +} + +/// The Idea is to transform individual timelines per system to a map of all +/// cores and what they (prob) are working on. +/// +/// # Example +/// +/// - Input: 3 services, 0 and 1 are 100% parallel and 2 is single threaded. `-` +/// means no work for *0.5s*. `#` means full work for *0.5s*. We see the first +/// service starts after 1s and runs for 3s The second one starts a sec later +/// and runs for 4s. The last service runs 2.5s after the tick start and runs +/// for 1s. Read left to right. +/// ```ignore +/// [--######------] +/// [----########--] +/// [-----##-------] +/// ``` +/// +/// - Output: a Map that calculates where our 6 cores are spending their time. +/// Here each number means 50% of a core is working on it. A '-' represents an +/// idling core. We start with all 6 cores idling. Then all cores start to +/// work on task 0. 2s in, task1 starts and we have to split cores. 2.5s in +/// task2 starts. We have 6 physical threads but work to fill 13. Later task 2 +/// and task 0 will finish their work and give more threads for task 1 to work +/// on. Read top to bottom +/// ```ignore +/// 0-1s [------------] +/// 1-2s [000000000000] +/// 2-2.5s [000000111111] +/// 2.5-3.5s [000001111122] +/// 3.5-4s [000000111111] +/// 4-6s [111111111111] +/// 6s.. [------------] +/// ``` +pub fn gen_stats( + timelines: &HashMap, + tick_work_start: Instant, + rayon_threads: u16, + physical_threads: u16, +) -> HashMap { + let mut result = HashMap::new(); + let mut all = timelines + .iter() + .map(|(s, t)| { + let mut stat = CpuTimeStats::default(); + stat.measures.push((0, 0.0)); + result.insert(s.clone(), stat); + t.measures.iter().map(|e| &e.0) + }) + .flatten() + .collect::>(); + + all.sort(); + all.dedup(); + for time in all { + let relative_time = time.duration_since(tick_work_start).as_nanos() as u64; + // get all parallelisation at this particular time + let individual_cores_wanted = timelines + .iter() + .map(|(k, t)| (k, t.get(*time).threads(rayon_threads))) + .collect::>(); + let total = individual_cores_wanted + .iter() + .map(|(_, a)| a) + .sum::() + .max(1) as f32; + let total_or_max = total.max(physical_threads as f32); + // update ALL states + for individual in individual_cores_wanted.iter() { + let actual = (individual.1 as f32 / total_or_max) * physical_threads as f32; + let p = result.get_mut(individual.0).unwrap(); + if (p.measures.last().unwrap().1 - actual).abs() > 0.0001 { + p.measures.push((relative_time, actual)); + } + } + } + result +} + +/// This trait wraps around specs::System and does additional veloren tasks like +/// metrics collection +/// +/// ``` +/// use specs::Read; +/// pub use veloren_common::vsystem::{Origin, ParMode, Phase, VJob, VSystem}; +/// # use std::time::Duration; +/// pub struct Sys; +/// impl<'a> VSystem<'a> for Sys { +/// type SystemData = (Read<'a, ()>, Read<'a, ()>); +/// +/// const NAME: &'static str = "example"; +/// const ORIGIN: Origin = Origin::Frontend("voxygen"); +/// const PHASE: Phase = Phase::Create; +/// +/// fn run(job: &mut VJob, (_read, _read2): Self::SystemData) { +/// std::thread::sleep(Duration::from_millis(100)); +/// job.cpu_stats.measure(ParMode::Rayon); +/// std::thread::sleep(Duration::from_millis(500)); +/// job.cpu_stats.measure(ParMode::Single); +/// std::thread::sleep(Duration::from_millis(40)); +/// } +/// } +/// ``` +pub trait VSystem<'a> { + const NAME: &'static str; + const PHASE: Phase; + const ORIGIN: Origin; + + type SystemData: specs::SystemData<'a>; + fn run(job: &mut VJob, data: Self::SystemData); + fn sys_name() -> String { format!("{}_sys", Self::NAME) } +} + +pub fn dispatch<'a, 'b, T>(builder: &mut specs::DispatcherBuilder<'a, 'b>, dep: &[&str]) +where + T: for<'c> VSystem<'c> + Send + 'a + Default, +{ + builder.add(VJob::::default(), &T::sys_name(), dep); +} + +pub fn run_now<'a, 'b, T>(world: &'a specs::World) +where + T: for<'c> VSystem<'c> + Send + 'a + Default, +{ + VJob::::default().run_now(world); +} + +/// This Struct will wrap the System in order to avoid the can only impl trait +/// for local defined structs error It also contains the cpu measurements +pub struct VJob +where + T: ?Sized, +{ + pub own: Box, + pub cpu_stats: CpuTimeline, +} + +impl<'a, T> System<'a> for VJob +where + T: VSystem<'a>, +{ + type SystemData = (T::SystemData, ReadExpect<'a, SysMetrics>); + + fn run(&mut self, data: Self::SystemData) { + crate::span!(_guard, "run", &format!("{}::Sys::run", T::NAME)); + self.cpu_stats.reset(); + T::run(self, data.0); + self.cpu_stats.end(); + data.1 + .stats + .lock() + .unwrap() + .insert(T::NAME.to_string(), self.cpu_stats.clone()); + } +} + +impl<'a, T> Default for VJob +where + T: VSystem<'a> + Default, +{ + fn default() -> Self { + Self { + own: Box::new(T::default()), + cpu_stats: CpuTimeline::default(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use float_cmp::approx_eq; + use std::time::Duration; + + fn mock_timelines( + tick_start: Instant, + durations: Vec<(u64, u64, ParMode)>, + ) -> HashMap { + let job = durations + .iter() + .enumerate() + .map(|(i, (s, e, p))| { + ( + i, + tick_start + Duration::from_millis(*s), + tick_start + Duration::from_millis(*e), + *p, + ) + }) + .collect::>(); + + job.iter() + .map(|(i, f, s, p)| { + (i.to_string(), CpuTimeline { + measures: vec![(*f, *p), (*s, ParMode::None)], + }) + }) + .collect() + } + + #[test] + fn single() { + const RAYON_THREADS: u16 = 4; + const PHYSICAL_THREADS: u16 = RAYON_THREADS; + let tick_start = Instant::now(); + let job_d = vec![(500, 1500, ParMode::Rayon)]; + let timelines = mock_timelines(tick_start, job_d); + + let stats = gen_stats(&timelines, tick_start, RAYON_THREADS, PHYSICAL_THREADS); + + const THREADS: f32 = PHYSICAL_THREADS as f32; + + let s = &stats["0"]; + let measures = &s.measures; + assert_eq!(measures.len(), 3); + assert_eq!(measures[0].0, 0); + assert!(approx_eq!(f32, measures[0].1, 0.0)); + assert_eq!(measures[1].0, 500000000); + assert!(approx_eq!(f32, measures[1].1, THREADS)); + assert_eq!(measures[2].0, 1500000000); + assert!(approx_eq!(f32, measures[2].1, 0.0)); + assert_eq!(s.start_ns(), 500000000); + assert_eq!(s.end_ns(), 1500000000); + assert_eq!(s.length_ns(), 1000000000); + assert!(approx_eq!(f32, s.avg_threads(), THREADS)); + } + + #[test] + fn two_jobs() { + const RAYON_THREADS: u16 = 8; + const PHYSICAL_THREADS: u16 = RAYON_THREADS; + let tick_start = Instant::now(); + let job_d = vec![(2000, 3000, ParMode::Single), (5000, 6500, ParMode::Single)]; + let timelines = mock_timelines(tick_start, job_d); + + let stats = gen_stats(&timelines, tick_start, RAYON_THREADS, PHYSICAL_THREADS); + + let s = &stats["0"]; + let measures = &s.measures; + assert_eq!(measures.len(), 3); + assert_eq!(measures[0].0, 0); + assert!(approx_eq!(f32, measures[0].1, 0.0)); + assert_eq!(measures[1].0, 2000000000); + assert!(approx_eq!(f32, measures[1].1, 1.0)); + assert_eq!(measures[2].0, 3000000000); + assert!(approx_eq!(f32, measures[2].1, 0.0)); + assert_eq!(s.start_ns(), 2000000000); + assert_eq!(s.end_ns(), 3000000000); + assert_eq!(s.length_ns(), 1000000000); + assert!(approx_eq!(f32, s.avg_threads(), 1.0)); + + let s = &stats["1"]; + let measures = &s.measures; + assert_eq!(measures.len(), 3); + assert_eq!(measures[0].0, 0); + assert!(approx_eq!(f32, measures[0].1, 0.0)); + assert_eq!(measures[1].0, 5000000000); + assert!(approx_eq!(f32, measures[1].1, 1.0)); + assert_eq!(measures[2].0, 6500000000); + assert!(approx_eq!(f32, measures[2].1, 0.0)); + assert_eq!(s.start_ns(), 5000000000); + assert_eq!(s.end_ns(), 6500000000); + assert_eq!(s.length_ns(), 1500000000); + assert!(approx_eq!(f32, s.avg_threads(), 1.0)); + } + + #[test] + fn generate_stats() { + const RAYON_THREADS: u16 = 6; + const PHYSICAL_THREADS: u16 = RAYON_THREADS; + let tick_start = Instant::now(); + let job_d = vec![ + (2000, 5000, ParMode::Rayon), + (3000, 7000, ParMode::Rayon), + (3500, 4500, ParMode::Single), + ]; + let timelines = mock_timelines(tick_start, job_d); + + let stats = gen_stats(&timelines, tick_start, RAYON_THREADS, PHYSICAL_THREADS); + + const THREADS: f32 = PHYSICAL_THREADS as f32; + + let s = &stats["0"]; + let measures = &s.measures; + assert_eq!(measures.len(), 6); + assert_eq!(measures[0].0, 0); + assert!(approx_eq!(f32, measures[0].1, 0.0)); + assert_eq!(measures[1].0, 2000000000); + assert!(approx_eq!(f32, measures[1].1, THREADS)); + assert_eq!(measures[2].0, 3000000000); + assert!(approx_eq!(f32, measures[2].1, THREADS / 2.0)); + assert_eq!(measures[3].0, 3500000000); + assert!(approx_eq!( + f32, + measures[3].1, + THREADS * THREADS / (THREADS * 2.0 + 1.0) + )); + assert_eq!(measures[4].0, 4500000000); + assert!(approx_eq!(f32, measures[4].1, THREADS / 2.0)); + assert_eq!(measures[5].0, 5000000000); + assert!(approx_eq!(f32, measures[5].1, 0.0)); + assert_eq!(s.start_ns(), 2000000000); + assert_eq!(s.end_ns(), 5000000000); + assert_eq!(s.length_ns(), 3000000000); + assert!(approx_eq!(f32, s.avg_threads(), 3.923077)); + + let s = &stats["1"]; + let measures = &s.measures; + assert_eq!(measures.len(), 6); + assert_eq!(measures[0].0, 0); + assert!(approx_eq!(f32, measures[0].1, 0.0)); + assert_eq!(measures[1].0, 3000000000); + assert!(approx_eq!(f32, measures[1].1, THREADS / 2.0)); + assert_eq!(measures[2].0, 3500000000); + assert!(approx_eq!( + f32, + measures[2].1, + THREADS * THREADS / (THREADS * 2.0 + 1.0) + )); + assert_eq!(measures[3].0, 4500000000); + assert!(approx_eq!(f32, measures[3].1, THREADS / 2.0)); + assert_eq!(measures[4].0, 5000000000); + assert!(approx_eq!(f32, measures[4].1, THREADS)); + assert_eq!(measures[5].0, 7000000000); + assert!(approx_eq!(f32, measures[5].1, 0.0)); + assert_eq!(s.start_ns(), 3000000000); + assert_eq!(s.end_ns(), 7000000000); + assert_eq!(s.length_ns(), 4000000000); + assert!(approx_eq!(f32, s.avg_threads(), 4.4423075)); + + let s = &stats["2"]; + let measures = &s.measures; + assert_eq!(measures.len(), 3); + assert_eq!(measures[0].0, 0); + assert!(approx_eq!(f32, measures[0].1, 0.0)); + assert_eq!(measures[1].0, 3500000000); + assert!(approx_eq!( + f32, + measures[1].1, + THREADS / (THREADS * 2.0 + 1.0) + )); + assert_eq!(measures[2].0, 4500000000); + assert!(approx_eq!(f32, measures[2].1, 0.0)); + assert_eq!(s.start_ns(), 3500000000); + assert_eq!(s.end_ns(), 4500000000); + assert_eq!(s.length_ns(), 1000000000); + assert!(approx_eq!(f32, s.avg_threads(), 0.4615385)); + } +} diff --git a/common/sys/src/aura.rs b/common/sys/src/aura.rs index 3a7dda3f6b..e1bd0628b6 100644 --- a/common/sys/src/aura.rs +++ b/common/sys/src/aura.rs @@ -8,10 +8,11 @@ use common::{ event::{EventBus, ServerEvent}, resources::DeltaTime, uid::UidAllocator, + vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, System, - SystemData, World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, + World, WriteStorage, }; use std::time::Duration; @@ -27,15 +28,20 @@ pub struct ReadData<'a> { groups: ReadStorage<'a, Group>, } +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Auras>, WriteStorage<'a, Buffs>, ); - fn run(&mut self, (read_data, mut auras, mut buffs): Self::SystemData) { + const NAME: &'static str = "aura"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut VJob, (read_data, mut auras, mut buffs): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); let dt = read_data.dt.0; diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index 0f4cdf130d..99564ecc84 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -7,11 +7,12 @@ use common::{ event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, uid::{Uid, UidAllocator}, + vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, System, - SystemData, World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, + World, WriteStorage, }; use std::time::Duration; use vek::*; @@ -37,15 +38,20 @@ pub struct ReadData<'a> { } /// This system is responsible for handling beams that heal or do damage +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, BeamSegment>, WriteStorage<'a, Beam>, ); - fn run(&mut self, (read_data, mut beam_segments, mut beams): Self::SystemData) { + const NAME: &'static str = "beam"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut VJob, (read_data, mut beam_segments, mut beams): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); let time = read_data.time.0; diff --git a/common/sys/src/buff.rs b/common/sys/src/buff.rs index 2a2aaa8c05..3f2d24e0aa 100644 --- a/common/sys/src/buff.rs +++ b/common/sys/src/buff.rs @@ -5,10 +5,11 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::DeltaTime, + vsystem::{Origin, Phase, VJob, VSystem}, Damage, DamageSource, }; use specs::{ - shred::ResourceId, Entities, Join, Read, ReadStorage, System, SystemData, World, WriteStorage, + shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, World, WriteStorage, }; use std::time::Duration; @@ -20,8 +21,9 @@ pub struct ReadData<'a> { inventories: ReadStorage<'a, Inventory>, } +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Health>, @@ -30,8 +32,12 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Stats>, ); + const NAME: &'static str = "buff"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, (read_data, mut healths, mut energies, mut buffs, mut stats): Self::SystemData, ) { let mut server_emitter = read_data.server_bus.emitter(); diff --git a/common/sys/src/character_behavior.rs b/common/sys/src/character_behavior.rs index fc83ab21ec..b03b1b1c72 100644 --- a/common/sys/src/character_behavior.rs +++ b/common/sys/src/character_behavior.rs @@ -1,6 +1,6 @@ use specs::{ - shred::ResourceId, Entities, Join, LazyUpdate, Read, ReadExpect, ReadStorage, System, - SystemData, World, WriteStorage, + shred::ResourceId, Entities, Join, LazyUpdate, Read, ReadExpect, ReadStorage, SystemData, + World, WriteStorage, }; use common::{ @@ -15,12 +15,12 @@ use common::{ event::{EventBus, LocalEvent, ServerEvent}, metrics::SysMetrics, resources::DeltaTime, - span, states::{ self, behavior::{CharacterBehavior, JoinData, JoinStruct}, }, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; use std::time::Duration; @@ -72,9 +72,10 @@ pub struct ReadData<'a> { /// ## Character Behavior System /// Passes `JoinData` to `CharacterState`'s `behavior` handler fn's. Receives a /// `StateUpdate` in return and performs updates to ECS Components from that. +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, @@ -88,9 +89,13 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Poise>, ); + const NAME: &'static str = "character_behavior"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + #[allow(clippy::while_let_on_iterator)] // TODO: Pending review in #587 fn run( - &mut self, + _job: &mut VJob, ( read_data, mut character_states, @@ -104,7 +109,6 @@ impl<'a> System<'a> for Sys { ): Self::SystemData, ) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "character_behavior::Sys::run"); let mut server_emitter = read_data.server_bus.emitter(); let mut local_emitter = read_data.local_bus.emitter(); diff --git a/common/sys/src/controller.rs b/common/sys/src/controller.rs index 8618c55e97..f83e806516 100644 --- a/common/sys/src/controller.rs +++ b/common/sys/src/controller.rs @@ -2,13 +2,13 @@ use common::{ comp::{BuffChange, ControlEvent, Controller}, event::{EventBus, ServerEvent}, metrics::SysMetrics, - span, uid::UidAllocator, + vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::{Marker, MarkerAllocator}, shred::ResourceId, - Entities, Join, Read, ReadExpect, System, SystemData, World, WriteStorage, + Entities, Join, Read, ReadExpect, SystemData, World, WriteStorage, }; use vek::*; @@ -20,14 +20,18 @@ pub struct ReadData<'a> { metrics: ReadExpect<'a, SysMetrics>, } +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = (ReadData<'a>, WriteStorage<'a, Controller>); - fn run(&mut self, (read_data, mut controllers): Self::SystemData) { + const NAME: &'static str = "controller"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut VJob, (read_data, mut controllers): Self::SystemData) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "controller::Sys::run"); let mut server_emitter = read_data.server_bus.emitter(); for (entity, controller) in (&read_data.entities, &mut controllers).join() { diff --git a/common/sys/src/lib.rs b/common/sys/src/lib.rs index 560e56af65..72da8cf129 100644 --- a/common/sys/src/lib.rs +++ b/common/sys/src/lib.rs @@ -15,33 +15,23 @@ pub mod state; mod stats; // External +use common::vsystem::{dispatch, VSystem}; use specs::DispatcherBuilder; -// System names -pub const CHARACTER_BEHAVIOR_SYS: &str = "character_behavior_sys"; -pub const MELEE_SYS: &str = "melee_sys"; -pub const BEAM_SYS: &str = "beam_sys"; -pub const CONTROLLER_SYS: &str = "controller_sys"; -pub const MOUNT_SYS: &str = "mount_sys"; -pub const PHYS_SYS: &str = "phys_sys"; -pub const PROJECTILE_SYS: &str = "projectile_sys"; -pub const SHOCKWAVE_SYS: &str = "shockwave_sys"; -pub const STATS_SYS: &str = "stats_sys"; -pub const BUFFS_SYS: &str = "buffs_sys"; -pub const AURAS_SYS: &str = "auras_sys"; - pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { - dispatch_builder.add(mount::Sys, MOUNT_SYS, &[]); - dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[MOUNT_SYS]); - dispatch_builder.add(character_behavior::Sys, CHARACTER_BEHAVIOR_SYS, &[ - CONTROLLER_SYS, + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[&mount::Sys::sys_name()]); + dispatch::(dispatch_builder, &[&controller::Sys::sys_name()]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[ + &controller::Sys::sys_name(), + &mount::Sys::sys_name(), + &stats::Sys::sys_name(), ]); - dispatch_builder.add(stats::Sys, STATS_SYS, &[]); - dispatch_builder.add(buff::Sys, BUFFS_SYS, &[]); - dispatch_builder.add(phys::Sys, PHYS_SYS, &[CONTROLLER_SYS, MOUNT_SYS, STATS_SYS]); - dispatch_builder.add(projectile::Sys, PROJECTILE_SYS, &[PHYS_SYS]); - dispatch_builder.add(shockwave::Sys, SHOCKWAVE_SYS, &[PHYS_SYS]); - dispatch_builder.add(beam::Sys, BEAM_SYS, &[PHYS_SYS]); - dispatch_builder.add(melee::Sys, MELEE_SYS, &[PROJECTILE_SYS]); - dispatch_builder.add(aura::Sys, AURAS_SYS, &[]); + dispatch::(dispatch_builder, &[&phys::Sys::sys_name()]); + dispatch::(dispatch_builder, &[&phys::Sys::sys_name()]); + dispatch::(dispatch_builder, &[&phys::Sys::sys_name()]); + dispatch::(dispatch_builder, &[&projectile::Sys::sys_name()]); + dispatch::(dispatch_builder, &[]); } diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index 548b76f143..72dd435cb5 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -3,13 +3,13 @@ use common::{ comp::{Body, CharacterState, Energy, Group, Health, Inventory, Melee, Ori, Pos, Scale, Stats}, event::{EventBus, ServerEvent}, metrics::SysMetrics, - span, uid::Uid, util::Dir, + vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ - shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, System, SystemData, World, + shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, WriteStorage, }; use vek::*; @@ -34,14 +34,18 @@ pub struct ReadData<'a> { /// This system is responsible for handling accepted inputs like moving or /// attacking +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = (ReadData<'a>, WriteStorage<'a, Melee>); - fn run(&mut self, (read_data, mut melee_attacks): Self::SystemData) { + const NAME: &'static str = "melee"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut VJob, (read_data, mut melee_attacks): Self::SystemData) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "melee::Sys::run"); let mut server_emitter = read_data.server_bus.emitter(); // Attacks for (attacker, uid, pos, ori, melee_attack, body) in ( diff --git a/common/sys/src/mount.rs b/common/sys/src/mount.rs index 80b71cfed5..44991b211a 100644 --- a/common/sys/src/mount.rs +++ b/common/sys/src/mount.rs @@ -1,18 +1,19 @@ use common::{ comp::{Controller, MountState, Mounting, Ori, Pos, Vel}, metrics::SysMetrics, - span, uid::UidAllocator, + vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::{Marker, MarkerAllocator}, - Entities, Join, Read, ReadExpect, System, WriteStorage, + Entities, Join, Read, ReadExpect, WriteStorage, }; use vek::*; /// This system is responsible for controlling mounts +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, UidAllocator>, @@ -26,8 +27,12 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Ori>, ); + const NAME: &'static str = "mount"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( uid_allocator, sys_metrics, @@ -41,7 +46,6 @@ impl<'a> System<'a> for Sys { ): Self::SystemData, ) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "mount::Sys::run"); // Mounted entities. for (entity, mut mount_states) in (&entities, &mut mount_state.restrict_mut()).join() { match mount_states.get_unchecked() { diff --git a/common/sys/src/phys.rs b/common/sys/src/phys.rs index f576447082..3f05858fd1 100644 --- a/common/sys/src/phys.rs +++ b/common/sys/src/phys.rs @@ -11,11 +11,10 @@ use common::{ terrain::{Block, TerrainGrid}, uid::Uid, vol::ReadVol, + vsystem::{Origin, ParMode, Phase, VJob, VSystem}, }; use rayon::iter::ParallelIterator; -use specs::{ - Entities, Join, ParJoin, Read, ReadExpect, ReadStorage, System, WriteExpect, WriteStorage, -}; +use specs::{Entities, Join, ParJoin, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage}; use std::ops::Range; use vek::*; @@ -61,9 +60,10 @@ fn calc_z_limit( } /// This system applies forces and calculates new positions and velocities. +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -90,10 +90,14 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, CharacterState>, ); + const NAME: &'static str = "phys"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587 fn run( - &mut self, + job: &mut VJob, ( entities, uids, @@ -120,7 +124,6 @@ impl<'a> System<'a> for Sys { ): Self::SystemData, ) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "phys::Sys::run"); let mut event_emitter = event_bus.emitter(); // Add/reset physics state components @@ -212,6 +215,7 @@ impl<'a> System<'a> for Sys { drop(guard); span!(guard, "Apply pushback"); + job.cpu_stats.measure(ParMode::Rayon); let metrics = ( &entities, &positions, @@ -776,6 +780,7 @@ impl<'a> System<'a> for Sys { land_on_grounds_a }); drop(guard); + job.cpu_stats.measure(ParMode::Single); land_on_grounds.into_iter().for_each(|(entity, vel)| { event_emitter.emit(ServerEvent::LandOnGround { entity, vel: vel.0 }); diff --git a/common/sys/src/projectile.rs b/common/sys/src/projectile.rs index 45701c3cb3..ed9cd79abe 100644 --- a/common/sys/src/projectile.rs +++ b/common/sys/src/projectile.rs @@ -7,14 +7,14 @@ use common::{ event::{EventBus, ServerEvent}, metrics::SysMetrics, resources::DeltaTime, - span, uid::UidAllocator, util::Dir, + vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, - System, SystemData, World, WriteStorage, + SystemData, World, WriteStorage, }; use std::time::Duration; @@ -35,17 +35,24 @@ pub struct ReadData<'a> { } /// This system is responsible for handling projectile effect triggers +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Ori>, WriteStorage<'a, Projectile>, ); - fn run(&mut self, (read_data, mut orientations, mut projectiles): Self::SystemData) { + const NAME: &'static str = "projectile"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + + fn run( + _job: &mut VJob, + (read_data, mut orientations, mut projectiles): Self::SystemData, + ) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "projectile::Sys::run"); let mut server_emitter = read_data.server_bus.emitter(); // Attacks diff --git a/common/sys/src/shockwave.rs b/common/sys/src/shockwave.rs index 80b5a12efa..5699b1b22f 100644 --- a/common/sys/src/shockwave.rs +++ b/common/sys/src/shockwave.rs @@ -8,11 +8,12 @@ use common::{ resources::{DeltaTime, Time}, uid::{Uid, UidAllocator}, util::Dir, + vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, System, - SystemData, World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, + World, WriteStorage, }; use vek::*; @@ -39,15 +40,23 @@ pub struct ReadData<'a> { /// This system is responsible for handling accepted inputs like moving or /// attacking +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Shockwave>, WriteStorage<'a, ShockwaveHitEntities>, ); - fn run(&mut self, (read_data, mut shockwaves, mut shockwave_hit_lists): Self::SystemData) { + const NAME: &'static str = "shockwave"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + + fn run( + _job: &mut VJob, + (read_data, mut shockwaves, mut shockwave_hit_lists): Self::SystemData, + ) { let mut server_emitter = read_data.server_bus.emitter(); let time = read_data.time.0; diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index fa9fdb8e21..1f900819b0 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -8,13 +8,13 @@ use common::{ metrics::SysMetrics, outcome::Outcome, resources::{DeltaTime, Time}, - span, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; use hashbrown::HashSet; use specs::{ - shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, System, SystemData, World, - Write, WriteStorage, + shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, Write, + WriteStorage, }; use vek::Vec3; @@ -36,8 +36,9 @@ pub struct ReadData<'a> { } /// This system kills players, levels them up, and regenerates energy. +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, @@ -49,8 +50,12 @@ impl<'a> System<'a> for Sys { Write<'a, Vec>, ); + const NAME: &'static str = "stats"; + const ORIGIN: Origin = Origin::Common; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( read_data, mut stats, @@ -62,7 +67,6 @@ impl<'a> System<'a> for Sys { ): Self::SystemData, ) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "stats::Sys::run"); let mut server_event_emitter = read_data.server_bus.emitter(); let dt = read_data.dt.0; diff --git a/server/src/lib.rs b/server/src/lib.rs index 8215c01e48..8e41ff8b89 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -66,6 +66,7 @@ use common::{ rtsim::RtSimEntity, terrain::TerrainChunkSize, vol::{ReadVol, RectVolSize}, + vsystem::run_now, }; use common_net::{ msg::{ @@ -87,11 +88,11 @@ use persistence::{ use plugin_api::Uid; use prometheus::Registry; use prometheus_hyper::Server as PrometheusServer; -use specs::{join::Join, Builder, Entity as EcsEntity, RunNow, SystemData, WorldExt}; +use specs::{join::Join, Builder, Entity as EcsEntity, SystemData, WorldExt}; use std::{ i32, ops::{Deref, DerefMut}, - sync::{atomic::Ordering, Arc}, + sync::Arc, time::{Duration, Instant}, }; #[cfg(not(feature = "worldgen"))] @@ -510,12 +511,12 @@ impl Server { // Run message receiving sys before the systems in common for decreased latency // (e.g. run before controller system) //TODO: run in parallel - sys::msg::general::Sys.run_now(&self.state.ecs()); + run_now::(&self.state.ecs()); self.register_run(); - sys::msg::character_screen::Sys.run_now(&self.state.ecs()); - sys::msg::in_game::Sys.run_now(&self.state.ecs()); - sys::msg::ping::Sys.run_now(&self.state.ecs()); - sys::agent::Sys.run_now(&self.state.ecs()); + run_now::(&self.state.ecs()); + run_now::(&self.state.ecs()); + run_now::(&self.state.ecs()); + run_now::(&self.state.ecs()); let before_state_tick = Instant::now(); @@ -705,6 +706,29 @@ impl Server { // 8) Update Metrics // Get system timing info + + { + let lock = self + .state + .ecs() + .read_resource::(); + let state = lock.stats.lock().unwrap(); + for (name, stat) in common::vsystem::gen_stats(&state, before_new_connections, 8, 8) { + self.tick_metrics + .system_start_time + .with_label_values(&[&name]) + .set(stat.start_ns() as i64); + self.tick_metrics + .system_length_time + .with_label_values(&[&name]) + .set(stat.length_ns() as i64); + self.tick_metrics + .system_thread_avg + .with_label_values(&[&name]) + .set(stat.avg_threads() as f64); + } + } + let agent_nanos = self.state.ecs().read_resource::().nanos as i64; let entity_sync_nanos = self .state @@ -819,6 +843,7 @@ impl Server { //detailed state metrics { + /* let res = self .state .ecs() @@ -834,7 +859,7 @@ impl Server { let melee_ns = res.melee_ns.load(Ordering::Relaxed); c.with_label_values(&[sys::AGENT_SYS]).inc_by(agent_ns); - c.with_label_values(&[common_sys::MOUNT_SYS]) + c.with_label_values(&[common_sys::]) .inc_by(mount_ns); c.with_label_values(&[common_sys::CONTROLLER_SYS]) .inc_by(controller_ns); @@ -866,6 +891,7 @@ impl Server { .observe(projectile_ns as f64 / NANOSEC_PER_SEC); h.with_label_values(&[common_sys::MELEE_SYS]) .observe(melee_ns as f64 / NANOSEC_PER_SEC); + */ } //detailed physics metrics diff --git a/server/src/metrics.rs b/server/src/metrics.rs index ac57121437..622cd4006c 100644 --- a/server/src/metrics.rs +++ b/server/src/metrics.rs @@ -1,6 +1,6 @@ use prometheus::{ - Gauge, HistogramOpts, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Opts, - Registry, + Gauge, GaugeVec, HistogramOpts, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, + Opts, Registry, }; use std::{ convert::TryInto, @@ -54,6 +54,9 @@ pub struct TickMetrics { pub start_time: IntGauge, pub time_of_day: Gauge, pub light_count: IntGauge, + pub system_start_time: IntGaugeVec, + pub system_length_time: IntGaugeVec, + pub system_thread_avg: GaugeVec, tick: Arc, } @@ -290,6 +293,24 @@ impl TickMetrics { Opts::new("tick_time", "time in ns required for a tick of the server"), &["period"], )?; + let system_start_time = IntGaugeVec::new( + Opts::new( + "system_start_time", + "start relative to tick start in ns required per ECS system", + ), + &["system"], + )?; + let system_length_time = IntGaugeVec::new( + Opts::new("system_length_time", "time in ns required per ECS system"), + &["system"], + )?; + let system_thread_avg = GaugeVec::new( + Opts::new( + "system_thread_avg", + "average threads used by the ECS system", + ), + &["system"], + )?; let since_the_epoch = SystemTime::now() .duration_since(UNIX_EPOCH) @@ -306,6 +327,9 @@ impl TickMetrics { let light_count_clone = light_count.clone(); let tick_time_clone = tick_time.clone(); let tick = Arc::new(AtomicU64::new(0)); + let system_start_time_clone = system_start_time.clone(); + let system_length_time_clone = system_length_time.clone(); + let system_thread_avg_clone = system_thread_avg.clone(); let f = |registry: &Registry| { registry.register(Box::new(chonks_count_clone))?; @@ -317,6 +341,9 @@ impl TickMetrics { registry.register(Box::new(time_of_day_clone))?; registry.register(Box::new(light_count_clone))?; registry.register(Box::new(tick_time_clone))?; + registry.register(Box::new(system_start_time_clone))?; + registry.register(Box::new(system_length_time_clone))?; + registry.register(Box::new(system_thread_avg_clone))?; Ok(()) }; @@ -331,6 +358,9 @@ impl TickMetrics { start_time, time_of_day, light_count, + system_start_time, + system_length_time, + system_thread_avg, tick, }, Box::new(f), diff --git a/server/src/rtsim/load_chunks.rs b/server/src/rtsim/load_chunks.rs index 756b4c3f79..1dde223a96 100644 --- a/server/src/rtsim/load_chunks.rs +++ b/server/src/rtsim/load_chunks.rs @@ -1,13 +1,21 @@ use super::*; -use common::event::{EventBus, ServerEvent}; -use specs::{Read, System, WriteExpect}; +use common::{ + event::{EventBus, ServerEvent}, + vsystem::{Origin, Phase, VJob, VSystem}, +}; +use specs::{Read, WriteExpect}; +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = (Read<'a, EventBus>, WriteExpect<'a, RtSim>); - fn run(&mut self, (_server_event_bus, mut rtsim): Self::SystemData) { + const NAME: &'static str = "rtsim::load_chunks"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut VJob, (_server_event_bus, mut rtsim): Self::SystemData) { for _chunk in std::mem::take(&mut rtsim.chunks.chunks_to_load) { // TODO } diff --git a/server/src/rtsim/mod.rs b/server/src/rtsim/mod.rs index f2352c9168..6bdeb93f8f 100644 --- a/server/src/rtsim/mod.rs +++ b/server/src/rtsim/mod.rs @@ -12,6 +12,7 @@ use common::{ rtsim::{RtSimController, RtSimEntity, RtSimId}, terrain::TerrainChunk, vol::RectRasterableVol, + vsystem::{dispatch, VSystem}, }; use common_sys::state::State; use rand::prelude::*; @@ -72,14 +73,13 @@ impl RtSim { } } -const LOAD_CHUNK_SYS: &str = "rtsim_load_chunk_sys"; -const UNLOAD_CHUNK_SYS: &str = "rtsim_unload_chunk_sys"; -const TICK_SYS: &str = "rtsim_tick_sys"; - pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { - dispatch_builder.add(unload_chunks::Sys, UNLOAD_CHUNK_SYS, &[]); - dispatch_builder.add(load_chunks::Sys, LOAD_CHUNK_SYS, &[UNLOAD_CHUNK_SYS]); - dispatch_builder.add(tick::Sys, TICK_SYS, &[LOAD_CHUNK_SYS, UNLOAD_CHUNK_SYS]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[&unload_chunks::Sys::sys_name()]); + dispatch::(dispatch_builder, &[ + &load_chunks::Sys::sys_name(), + &unload_chunks::Sys::sys_name(), + ]); } pub fn init(state: &mut State, #[cfg(feature = "worldgen")] world: &world::World) { diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 002c414f23..afb8847e9a 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -7,14 +7,16 @@ use common::{ event::{EventBus, ServerEvent}, resources::DeltaTime, terrain::TerrainGrid, + vsystem::{Origin, Phase, VJob, VSystem}, }; -use specs::{Join, Read, ReadExpect, ReadStorage, System, WriteExpect, WriteStorage}; +use specs::{Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage}; use std::sync::Arc; const ENTITY_TICK_PERIOD: u64 = 30; +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, DeltaTime>, @@ -28,8 +30,12 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, comp::Agent>, ); + const NAME: &'static str = "rtsim::tick"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( dt, server_event_bus, diff --git a/server/src/rtsim/unload_chunks.rs b/server/src/rtsim/unload_chunks.rs index 1de4eb144b..f05800fb87 100644 --- a/server/src/rtsim/unload_chunks.rs +++ b/server/src/rtsim/unload_chunks.rs @@ -3,11 +3,13 @@ use common::{ comp::Pos, event::{EventBus, ServerEvent}, terrain::TerrainGrid, + vsystem::{Origin, Phase, VJob, VSystem}, }; -use specs::{Entities, Read, ReadExpect, ReadStorage, System, WriteExpect}; +use specs::{Entities, Read, ReadExpect, ReadStorage, WriteExpect}; +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, EventBus>, @@ -18,8 +20,12 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Pos>, ); + const NAME: &'static str = "rtsim::unload_chunks"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( _server_event_bus, mut rtsim, diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index ebdac75da4..b883765eba 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -19,20 +19,20 @@ use common::{ metrics::SysMetrics, path::TraversalConfig, resources::{DeltaTime, TimeOfDay}, - span, terrain::{Block, TerrainGrid}, time::DayPeriod, uid::{Uid, UidAllocator}, util::Dir, vol::ReadVol, + vsystem::{Origin, Phase, VJob, VSystem}, }; use rand::{thread_rng, Rng}; use rayon::iter::ParallelIterator; use specs::{ saveload::{Marker, MarkerAllocator}, shred::ResourceId, - Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, System, - SystemData, World, Write, WriteStorage, + Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, World, + Write, WriteStorage, }; use std::f32::consts::PI; use vek::*; @@ -99,8 +99,9 @@ const SNEAK_COEFFICIENT: f32 = 0.25; const AVG_FOLLOW_DIST: f32 = 6.0; /// This system will allow NPCs to modify their controller +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, @@ -110,13 +111,16 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Controller>, ); + const NAME: &'static str = "agent"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 fn run( - &mut self, + _job: &mut VJob, (read_data, mut sys_timer, event_bus, mut agents, mut controllers): Self::SystemData, ) { let start_time = std::time::Instant::now(); - span!(_guard, "run", "agent::Sys::run"); sys_timer.start(); ( diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 46315841d4..f48fa6ce42 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -12,20 +12,21 @@ use common::{ outcome::Outcome, region::{Event as RegionEvent, RegionMap}, resources::TimeOfDay, - span, terrain::TerrainChunkSize, uid::Uid, vol::RectVolSize, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::{msg::ServerGeneral, sync::CompSyncPackage}; use specs::{ - Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage, + Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage, }; use vek::*; /// This system will send physics updates to the client +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, @@ -52,8 +53,12 @@ impl<'a> System<'a> for Sys { ReadTrackers<'a>, ); + const NAME: &'static str = "entity_sync"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( entities, tick, @@ -79,7 +84,6 @@ impl<'a> System<'a> for Sys { trackers, ): Self::SystemData, ) { - span!(_guard, "run", "entity_sync::Sys::run"); timer.start(); let tick = tick.0; diff --git a/server/src/sys/invite_timeout.rs b/server/src/sys/invite_timeout.rs index 1bc1979cb1..37fd4bbc0f 100644 --- a/server/src/sys/invite_timeout.rs +++ b/server/src/sys/invite_timeout.rs @@ -2,15 +2,16 @@ use super::SysTimer; use crate::client::Client; use common::{ comp::invite::{Invite, PendingInvites}, - span, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{InviteAnswer, ServerGeneral}; -use specs::{Entities, Join, ReadStorage, System, Write, WriteStorage}; +use specs::{Entities, Join, ReadStorage, Write, WriteStorage}; /// This system removes timed out invites +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, @@ -21,11 +22,14 @@ impl<'a> System<'a> for Sys { Write<'a, SysTimer>, ); + const NAME: &'static str = "invite_timeout"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, (entities, mut invites, mut pending_invites, clients, uids, mut timer): Self::SystemData, ) { - span!(_guard, "run", "invite_timeout::Sys::run"); timer.start(); let now = std::time::Instant::now(); diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 649c52114b..bbd6a258e3 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -10,6 +10,7 @@ pub mod terrain; pub mod terrain_sync; pub mod waypoint; +use common::vsystem::{dispatch, run_now}; use specs::DispatcherBuilder; use std::{ marker::PhantomData, @@ -31,38 +32,23 @@ pub type PersistenceTimer = SysTimer; pub type PersistenceScheduler = SysScheduler; pub type AgentTimer = SysTimer; -// System names -// Note: commented names may be useful in the future -//const ENTITY_SYNC_SYS: &str = "server_entity_sync_sys"; -//const SENTINEL_SYS: &str = "sentinel_sys"; -//const SUBSCRIPTION_SYS: &str = "server_subscription_sys"; -//const TERRAIN_SYNC_SYS: &str = "server_terrain_sync_sys"; -const TERRAIN_SYS: &str = "server_terrain_sys"; -const WAYPOINT_SYS: &str = "server_waypoint_sys"; -const INVITE_TIMEOUT_SYS: &str = "server_invite_timeout_sys"; -const PERSISTENCE_SYS: &str = "server_persistence_sys"; -const OBJECT_SYS: &str = "server_object_sys"; -pub const AGENT_SYS: &str = "agent_sys"; - pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { - dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]); - dispatch_builder.add(waypoint::Sys, WAYPOINT_SYS, &[]); - dispatch_builder.add(invite_timeout::Sys, INVITE_TIMEOUT_SYS, &[]); - dispatch_builder.add(persistence::Sys, PERSISTENCE_SYS, &[]); - dispatch_builder.add(object::Sys, OBJECT_SYS, &[]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[]); } pub fn run_sync_systems(ecs: &mut specs::World) { - use specs::RunNow; - // Setup for entity sync // If I'm not mistaken, these two could be ran in parallel - sentinel::Sys.run_now(ecs); - subscription::Sys.run_now(ecs); + run_now::(ecs); + run_now::(ecs); // Sync - terrain_sync::Sys.run_now(ecs); - entity_sync::Sys.run_now(ecs); + run_now::(ecs); + run_now::(ecs); } /// Used to schedule systems to run at an interval diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index b3dd3ca57a..e3b8b8e1b2 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -6,11 +6,11 @@ use crate::{ use common::{ comp::{ChatType, Player, UnresolvedChatMsg}, event::{EventBus, ServerEvent}, - span, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ClientGeneral, ServerGeneral}; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write}; use std::sync::atomic::Ordering; use tracing::{debug, warn}; @@ -121,8 +121,9 @@ impl Sys { } /// This system will handle new messages from clients +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -137,8 +138,12 @@ impl<'a> System<'a> for Sys { ReadExpect<'a, AliasValidator>, ); + const NAME: &'static str = "msg::character_screen"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( entities, server_event_bus, @@ -152,7 +157,6 @@ impl<'a> System<'a> for Sys { alias_validator, ): Self::SystemData, ) { - span!(_guard, "run", "msg::character_screen::Sys::run"); timer.start(); let mut server_emitter = server_event_bus.emitter(); diff --git a/server/src/sys/msg/general.rs b/server/src/sys/msg/general.rs index 1200a74d0e..d928fea9b9 100644 --- a/server/src/sys/msg/general.rs +++ b/server/src/sys/msg/general.rs @@ -4,13 +4,13 @@ use common::{ comp::{ChatMode, Player, UnresolvedChatMsg}, event::{EventBus, ServerEvent}, resources::Time, - span, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ validate_chat_msg, ChatMsgValidationError, ClientGeneral, MAX_BYTES_CHAT_MSG, }; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write}; use std::sync::atomic::Ordering; use tracing::{debug, error, warn}; @@ -65,8 +65,9 @@ impl Sys { } /// This system will handle new messages from clients +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -80,8 +81,12 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Client>, ); + const NAME: &'static str = "msg::general"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( entities, server_event_bus, @@ -94,7 +99,6 @@ impl<'a> System<'a> for Sys { clients, ): Self::SystemData, ) { - span!(_guard, "run", "msg::general::Sys::run"); timer.start(); let mut server_emitter = server_event_bus.emitter(); diff --git a/server/src/sys/msg/in_game.rs b/server/src/sys/msg/in_game.rs index c8076c9bc6..454436a9e3 100644 --- a/server/src/sys/msg/in_game.rs +++ b/server/src/sys/msg/in_game.rs @@ -3,13 +3,13 @@ use crate::{client::Client, metrics::NetworkRequestMetrics, presence::Presence, use common::{ comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, Stats, Vel}, event::{EventBus, ServerEvent}, - span, terrain::{TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize}, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ClientGeneral, PresenceKind, ServerGeneral}; use common_sys::state::BlockChange; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage}; use tracing::{debug, trace}; impl Sys { @@ -165,8 +165,9 @@ impl Sys { } /// This system will handle new messages from clients +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -188,8 +189,12 @@ impl<'a> System<'a> for Sys { Read<'a, Settings>, ); + const NAME: &'static str = "msg::in_game"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( entities, server_event_bus, @@ -210,7 +215,6 @@ impl<'a> System<'a> for Sys { settings, ): Self::SystemData, ) { - span!(_guard, "run", "msg::in_game::Sys::run"); timer.start(); let mut server_emitter = server_event_bus.emitter(); diff --git a/server/src/sys/msg/ping.rs b/server/src/sys/msg/ping.rs index ea12514b1b..a80ee2799a 100644 --- a/server/src/sys/msg/ping.rs +++ b/server/src/sys/msg/ping.rs @@ -3,10 +3,10 @@ use crate::{client::Client, metrics::PlayerMetrics, Settings}; use common::{ event::{EventBus, ServerEvent}, resources::Time, - span, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::PingMsg; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write}; use std::sync::atomic::Ordering; use tracing::{debug, info}; @@ -21,8 +21,9 @@ impl Sys { } /// This system will handle new messages from clients +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -34,8 +35,12 @@ impl<'a> System<'a> for Sys { Read<'a, Settings>, ); + const NAME: &'static str = "msg::ping"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( entities, server_event_bus, @@ -46,7 +51,6 @@ impl<'a> System<'a> for Sys { settings, ): Self::SystemData, ) { - span!(_guard, "run", "msg::ping::Sys::run"); timer.start(); let mut server_emitter = server_event_bus.emitter(); diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index 0810017d93..a5aee2f43f 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -3,13 +3,15 @@ use common::{ effect::Effect, event::{EventBus, ServerEvent}, resources::DeltaTime, - span, Damage, DamageSource, Explosion, RadiusEffect, + vsystem::{Origin, Phase, VJob, VSystem}, + Damage, DamageSource, Explosion, RadiusEffect, }; -use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; +use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; /// This system is responsible for handling misc object behaviours +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -21,11 +23,14 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Object>, ); + const NAME: &'static str = "object"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, (entities, _dt, server_bus, positions, velocities, physics_states, mut objects): Self::SystemData, ) { - span!(_guard, "run", "object::Sys::run"); let mut server_emitter = server_bus.emitter(); // Objects diff --git a/server/src/sys/persistence.rs b/server/src/sys/persistence.rs index 2aecd80f75..858b8a5cf1 100644 --- a/server/src/sys/persistence.rs +++ b/server/src/sys/persistence.rs @@ -5,14 +5,15 @@ use crate::{ }; use common::{ comp::{Inventory, Stats, Waypoint}, - span, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::PresenceKind; -use specs::{Join, ReadExpect, ReadStorage, System, Write}; +use specs::{Join, ReadExpect, ReadStorage, Write}; +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( ReadStorage<'a, Presence>, @@ -24,8 +25,12 @@ impl<'a> System<'a> for Sys { Write<'a, SysTimer>, ); + const NAME: &'static str = "persistence"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( presences, player_stats, @@ -36,7 +41,6 @@ impl<'a> System<'a> for Sys { mut timer, ): Self::SystemData, ) { - span!(_guard, "run", "persistence::Sys::run"); if scheduler.should_run() { timer.start(); updater.batch_update( diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 517743f9e7..f6c9c38aaf 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -5,8 +5,8 @@ use common::{ Gravity, Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori, Player, Poise, Pos, Scale, Shockwave, Stats, Sticky, Vel, }, - span, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::{ msg::EcsCompPacket, @@ -14,24 +14,28 @@ use common_net::{ }; use hashbrown::HashMap; use specs::{ - shred::ResourceId, Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, SystemData, - World, Write, WriteExpect, + shred::ResourceId, Entity as EcsEntity, Join, ReadExpect, ReadStorage, SystemData, World, + Write, WriteExpect, }; use vek::*; /// Always watching /// This system will monitor specific components for insertion, removal, and /// modification +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { type SystemData = ( Write<'a, SysTimer>, TrackedComps<'a>, WriteTrackers<'a>, ); - fn run(&mut self, (mut timer, comps, mut trackers): Self::SystemData) { - span!(_guard, "run", "sentinel::Sys::run"); + const NAME: &'static str = "sentinel"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut VJob, (mut timer, comps, mut trackers): Self::SystemData) { timer.start(); record_changes(&comps, &mut trackers); diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index 66ac09ff48..e8ad98aec4 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -9,22 +9,22 @@ use crate::{ use common::{ comp::{Ori, Pos, Vel}, region::{region_in_vd, regions_in_vd, Event as RegionEvent, RegionMap}, - span, terrain::TerrainChunkSize, uid::Uid, vol::RectVolSize, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::ServerGeneral; use specs::{ - Entities, Join, ReadExpect, ReadStorage, System, SystemData, World, WorldExt, Write, - WriteStorage, + Entities, Join, ReadExpect, ReadStorage, SystemData, World, WorldExt, Write, WriteStorage, }; use tracing::{debug, error}; use vek::*; /// This system will update region subscriptions based on client positions +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, @@ -41,9 +41,13 @@ impl<'a> System<'a> for Sys { TrackedComps<'a>, ); + const NAME: &'static str = "subscription"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587 fn run( - &mut self, + _job: &mut VJob, ( entities, region_map, @@ -59,7 +63,6 @@ impl<'a> System<'a> for Sys { tracked_comps, ): Self::SystemData, ) { - span!(_guard, "run", "subscription::Sys::run"); timer.start(); // To update subscriptions diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 6c493baf7b..e99e4a4ca7 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -7,13 +7,13 @@ use common::{ event::{EventBus, ServerEvent}, generation::get_npc_name, npc::NPC_NAMES, - span, terrain::TerrainGrid, + vsystem::{Origin, Phase, VJob, VSystem}, LoadoutBuilder, SkillSetBuilder, }; use common_net::msg::ServerGeneral; use common_sys::state::TerrainChanges; -use specs::{Join, Read, ReadStorage, System, Write, WriteExpect}; +use specs::{Join, Read, ReadStorage, Write, WriteExpect}; use std::sync::Arc; use vek::*; @@ -23,8 +23,9 @@ use vek::*; /// 2. Sends new chunks to nearby clients /// 3. Handles the chunk's supplement (e.g. npcs) /// 4. Removes chunks outside the range of players +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Read<'a, EventBus>, @@ -39,8 +40,12 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Client>, ); + const NAME: &'static str = "terrain"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( server_event_bus, tick, @@ -54,7 +59,6 @@ impl<'a> System<'a> for Sys { clients, ): Self::SystemData, ) { - span!(_guard, "run", "terrain::Sys::run"); timer.start(); let mut server_emitter = server_event_bus.emitter(); diff --git a/server/src/sys/terrain_sync.rs b/server/src/sys/terrain_sync.rs index ffbfcfab60..2e52332036 100644 --- a/server/src/sys/terrain_sync.rs +++ b/server/src/sys/terrain_sync.rs @@ -1,14 +1,19 @@ use super::SysTimer; use crate::{client::Client, presence::Presence}; -use common::{comp::Pos, span, terrain::TerrainGrid}; +use common::{ + comp::Pos, + terrain::TerrainGrid, + vsystem::{Origin, Phase, VJob, VSystem}, +}; use common_net::msg::ServerGeneral; use common_sys::state::TerrainChanges; -use specs::{Join, Read, ReadExpect, ReadStorage, System, Write}; +use specs::{Join, Read, ReadExpect, ReadStorage, Write}; /// This systems sends new chunks to clients as well as changes to existing /// chunks +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( ReadExpect<'a, TerrainGrid>, @@ -19,11 +24,14 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Client>, ); + const NAME: &'static str = "terrain_sync"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, (terrain, terrain_changes, mut timer, positions, presences, clients): Self::SystemData, ) { - span!(_guard, "run", "terrain_sync::Sys::run"); timer.start(); // Sync changed chunks diff --git a/server/src/sys/waypoint.rs b/server/src/sys/waypoint.rs index de81c557bf..7d261cc3be 100644 --- a/server/src/sys/waypoint.rs +++ b/server/src/sys/waypoint.rs @@ -3,18 +3,19 @@ use crate::client::Client; use common::{ comp::{Player, Pos, Waypoint, WaypointArea}, resources::Time, - span, + vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{Notification, ServerGeneral}; -use specs::{Entities, Join, Read, ReadStorage, System, Write, WriteStorage}; +use specs::{Entities, Join, Read, ReadStorage, Write, WriteStorage}; /// Cooldown time (in seconds) for "Waypoint Saved" notifications const NOTIFY_TIME: f64 = 10.0; /// This system updates player waypoints /// TODO: Make this faster by only considering local waypoints +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, @@ -27,8 +28,12 @@ impl<'a> System<'a> for Sys { Write<'a, SysTimer>, ); + const NAME: &'static str = "waypoint"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, ( entities, positions, @@ -40,7 +45,6 @@ impl<'a> System<'a> for Sys { mut timer, ): Self::SystemData, ) { - span!(_guard, "run", "waypoint::Sys::run"); timer.start(); for (entity, player_pos, _, client) in (&entities, &positions, &players, &clients).join() { diff --git a/voxygen/src/ecs/sys.rs b/voxygen/src/ecs/sys.rs index a3b184effb..7405e0de8f 100644 --- a/voxygen/src/ecs/sys.rs +++ b/voxygen/src/ecs/sys.rs @@ -1,15 +1,10 @@ pub mod floater; mod interpolation; +use common::vsystem::{dispatch, VSystem}; use specs::DispatcherBuilder; -// System names -const FLOATER_SYS: &str = "floater_voxygen_sys"; -const INTERPOLATION_SYS: &str = "interpolation_voxygen_sys"; - pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { - dispatch_builder.add(interpolation::Sys, INTERPOLATION_SYS, &[ - common_sys::PHYS_SYS, - ]); - dispatch_builder.add(floater::Sys, FLOATER_SYS, &[INTERPOLATION_SYS]); + dispatch::(dispatch_builder, &[&common_sys::phys::Sys::sys_name()]); + dispatch::(dispatch_builder, &[&interpolation::Sys::sys_name()]); } diff --git a/voxygen/src/ecs/sys/floater.rs b/voxygen/src/ecs/sys/floater.rs index b19acf22e8..8e293ec2db 100644 --- a/voxygen/src/ecs/sys/floater.rs +++ b/voxygen/src/ecs/sys/floater.rs @@ -6,16 +6,18 @@ use common::{ comp::{Health, HealthSource, Pos}, resources::DeltaTime, uid::Uid, + vsystem::{Origin, Phase, VJob, VSystem}, }; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, WriteStorage}; // How long floaters last (in seconds) pub const HP_SHOWTIME: f32 = 3.0; pub const MY_HP_SHOWTIME: f32 = 2.5; pub const HP_ACCUMULATETIME: f32 = 1.0; +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, @@ -27,9 +29,13 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, HpFloaterList>, ); + const NAME: &'static str = "floater"; + const ORIGIN: Origin = Origin::Frontend("voxygen"); + const PHASE: Phase = Phase::Create; + #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587 fn run( - &mut self, + _job: &mut VJob, (entities, my_entity, dt, uids, pos, healths, mut hp_floater_lists): Self::SystemData, ) { // Add hp floater lists to all entities with health and a position diff --git a/voxygen/src/ecs/sys/interpolation.rs b/voxygen/src/ecs/sys/interpolation.rs index 9a09f852ee..4bd1489230 100644 --- a/voxygen/src/ecs/sys/interpolation.rs +++ b/voxygen/src/ecs/sys/interpolation.rs @@ -2,14 +2,16 @@ use crate::ecs::comp::Interpolated; use common::{ comp::{object, Body, Ori, Pos, Vel}, resources::DeltaTime, + vsystem::{Origin, Phase, VJob, VSystem}, }; -use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; +use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; use tracing::warn; use vek::*; /// This system will allow NPCs to modify their controller +#[derive(Default)] pub struct Sys; -impl<'a> System<'a> for Sys { +impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, @@ -21,8 +23,12 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Interpolated>, ); + const NAME: &'static str = "interpolation"; + const ORIGIN: Origin = Origin::Frontend("voxygen"); + const PHASE: Phase = Phase::Create; + fn run( - &mut self, + _job: &mut VJob, (entities, dt, positions, orientations, velocities, bodies, mut interpolated): Self::SystemData, ) { // Update interpolated positions and orientations From 6b8854548121706b5a62912c3ef78c070801fc11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Mon, 8 Mar 2021 09:36:53 +0100 Subject: [PATCH 2/5] restructure server metrics - get rid of old SysTimers for each system in favour of VSystem tracking - move metrics generation from lib.rs to own system - code cleanup - remove time tracking in common::sys --- common/src/metrics.rs | 13 +- common/sys/src/character_behavior.rs | 11 +- common/sys/src/controller.rs | 9 +- common/sys/src/melee.rs | 10 +- common/sys/src/mount.rs | 10 +- common/sys/src/phys.rs | 9 +- common/sys/src/projectile.rs | 11 +- common/sys/src/stats.rs | 11 +- server/src/lib.rs | 289 +++---------------------- server/src/metrics.rs | 98 ++++----- server/src/sys/agent.rs | 16 +- server/src/sys/entity_sync.rs | 13 +- server/src/sys/invite_timeout.rs | 13 +- server/src/sys/metrics.rs | 128 +++++++++++ server/src/sys/mod.rs | 49 +---- server/src/sys/msg/character_screen.rs | 9 +- server/src/sys/msg/general.rs | 9 +- server/src/sys/msg/in_game.rs | 7 - server/src/sys/msg/ping.rs | 18 +- server/src/sys/persistence.rs | 12 +- server/src/sys/sentinel.rs | 15 +- server/src/sys/subscription.rs | 13 +- server/src/sys/terrain.rs | 7 - server/src/sys/terrain_sync.rs | 12 +- server/src/sys/waypoint.rs | 11 +- voxygen/src/ecs/sys/floater.rs | 2 +- voxygen/src/ecs/sys/interpolation.rs | 2 +- 27 files changed, 241 insertions(+), 566 deletions(-) create mode 100644 server/src/sys/metrics.rs diff --git a/common/src/metrics.rs b/common/src/metrics.rs index 58ebf31627..d1f9a81997 100644 --- a/common/src/metrics.rs +++ b/common/src/metrics.rs @@ -1,20 +1,9 @@ use crate::vsystem::CpuTimeline; -use std::{ - collections::HashMap, - sync::{atomic::AtomicU64, Mutex}, -}; +use std::{collections::HashMap, sync::Mutex}; #[derive(Default)] pub struct SysMetrics { pub stats: Mutex>, - pub agent_ns: AtomicU64, - pub mount_ns: AtomicU64, - pub controller_ns: AtomicU64, - pub character_behavior_ns: AtomicU64, - pub stats_ns: AtomicU64, - pub phys_ns: AtomicU64, - pub projectile_ns: AtomicU64, - pub melee_ns: AtomicU64, } #[derive(Default)] diff --git a/common/sys/src/character_behavior.rs b/common/sys/src/character_behavior.rs index b03b1b1c72..1751d2d73f 100644 --- a/common/sys/src/character_behavior.rs +++ b/common/sys/src/character_behavior.rs @@ -1,6 +1,6 @@ use specs::{ - shred::ResourceId, Entities, Join, LazyUpdate, Read, ReadExpect, ReadStorage, SystemData, - World, WriteStorage, + shred::ResourceId, Entities, Join, LazyUpdate, Read, ReadStorage, SystemData, World, + WriteStorage, }; use common::{ @@ -13,7 +13,6 @@ use common::{ Ori, PhysicsState, Poise, PoiseState, Pos, StateUpdate, Stats, Vel, }, event::{EventBus, LocalEvent, ServerEvent}, - metrics::SysMetrics, resources::DeltaTime, states::{ self, @@ -56,7 +55,6 @@ pub struct ReadData<'a> { local_bus: Read<'a, EventBus>, dt: Read<'a, DeltaTime>, lazy_update: Read<'a, LazyUpdate>, - metrics: ReadExpect<'a, SysMetrics>, healths: ReadStorage<'a, Health>, bodies: ReadStorage<'a, Body>, physics_states: ReadStorage<'a, PhysicsState>, @@ -108,7 +106,6 @@ impl<'a> VSystem<'a> for Sys { mut poises, ): Self::SystemData, ) { - let start_time = std::time::Instant::now(); let mut server_emitter = read_data.server_bus.emitter(); let mut local_emitter = read_data.local_bus.emitter(); @@ -351,9 +348,5 @@ impl<'a> VSystem<'a> for Sys { server_emitter.append(&mut state_update.server_events); incorporate_update(&mut join_struct, state_update); } - read_data.metrics.character_behavior_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/common/sys/src/controller.rs b/common/sys/src/controller.rs index f83e806516..e16fb40c14 100644 --- a/common/sys/src/controller.rs +++ b/common/sys/src/controller.rs @@ -1,14 +1,13 @@ use common::{ comp::{BuffChange, ControlEvent, Controller}, event::{EventBus, ServerEvent}, - metrics::SysMetrics, uid::UidAllocator, vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::{Marker, MarkerAllocator}, shred::ResourceId, - Entities, Join, Read, ReadExpect, SystemData, World, WriteStorage, + Entities, Join, Read, SystemData, World, WriteStorage, }; use vek::*; @@ -17,7 +16,6 @@ pub struct ReadData<'a> { entities: Entities<'a>, uid_allocator: Read<'a, UidAllocator>, server_bus: Read<'a, EventBus>, - metrics: ReadExpect<'a, SysMetrics>, } #[derive(Default)] @@ -31,7 +29,6 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run(_job: &mut VJob, (read_data, mut controllers): Self::SystemData) { - let start_time = std::time::Instant::now(); let mut server_emitter = read_data.server_bus.emitter(); for (entity, controller) in (&read_data.entities, &mut controllers).join() { @@ -107,9 +104,5 @@ impl<'a> VSystem<'a> for Sys { } } } - read_data.metrics.controller_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index 72dd435cb5..5a84b3172a 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -2,15 +2,13 @@ use common::{ combat::{AttackerInfo, TargetInfo}, comp::{Body, CharacterState, Energy, Group, Health, Inventory, Melee, Ori, Pos, Scale, Stats}, event::{EventBus, ServerEvent}, - metrics::SysMetrics, uid::Uid, util::Dir, vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ - shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, - WriteStorage, + shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, World, WriteStorage, }; use vek::*; @@ -28,7 +26,6 @@ pub struct ReadData<'a> { groups: ReadStorage<'a, Group>, char_states: ReadStorage<'a, CharacterState>, server_bus: Read<'a, EventBus>, - metrics: ReadExpect<'a, SysMetrics>, stats: ReadStorage<'a, Stats>, } @@ -45,7 +42,6 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run(_job: &mut VJob, (read_data, mut melee_attacks): Self::SystemData) { - let start_time = std::time::Instant::now(); let mut server_emitter = read_data.server_bus.emitter(); // Attacks for (attacker, uid, pos, ori, melee_attack, body) in ( @@ -139,9 +135,5 @@ impl<'a> VSystem<'a> for Sys { } } } - read_data.metrics.melee_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/common/sys/src/mount.rs b/common/sys/src/mount.rs index 44991b211a..5b68cbe758 100644 --- a/common/sys/src/mount.rs +++ b/common/sys/src/mount.rs @@ -1,12 +1,11 @@ use common::{ comp::{Controller, MountState, Mounting, Ori, Pos, Vel}, - metrics::SysMetrics, uid::UidAllocator, vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::{Marker, MarkerAllocator}, - Entities, Join, Read, ReadExpect, WriteStorage, + Entities, Join, Read, WriteStorage, }; use vek::*; @@ -17,7 +16,6 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, UidAllocator>, - ReadExpect<'a, SysMetrics>, Entities<'a>, WriteStorage<'a, Controller>, WriteStorage<'a, MountState>, @@ -35,7 +33,6 @@ impl<'a> VSystem<'a> for Sys { _job: &mut VJob, ( uid_allocator, - sys_metrics, entities, mut controllers, mut mount_state, @@ -45,7 +42,6 @@ impl<'a> VSystem<'a> for Sys { mut orientations, ): Self::SystemData, ) { - let start_time = std::time::Instant::now(); // Mounted entities. for (entity, mut mount_states) in (&entities, &mut mount_state.restrict_mut()).join() { match mount_states.get_unchecked() { @@ -96,9 +92,5 @@ impl<'a> VSystem<'a> for Sys { for entity in to_unmount { mountings.remove(entity); } - sys_metrics.mount_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/common/sys/src/phys.rs b/common/sys/src/phys.rs index 3f05858fd1..e246fcabdb 100644 --- a/common/sys/src/phys.rs +++ b/common/sys/src/phys.rs @@ -5,7 +5,7 @@ use common::{ }, consts::{FRIC_GROUND, GRAVITY}, event::{EventBus, ServerEvent}, - metrics::{PhysicsMetrics, SysMetrics}, + metrics::PhysicsMetrics, resources::DeltaTime, span, terrain::{Block, TerrainGrid}, @@ -70,7 +70,6 @@ impl<'a> VSystem<'a> for Sys { ReadStorage<'a, Uid>, ReadExpect<'a, TerrainGrid>, Read<'a, DeltaTime>, - ReadExpect<'a, SysMetrics>, WriteExpect<'a, PhysicsMetrics>, Read<'a, EventBus>, ReadStorage<'a, Scale>, @@ -103,7 +102,6 @@ impl<'a> VSystem<'a> for Sys { uids, terrain, dt, - sys_metrics, mut physics_metrics, event_bus, scales, @@ -123,7 +121,6 @@ impl<'a> VSystem<'a> for Sys { char_states, ): Self::SystemData, ) { - let start_time = std::time::Instant::now(); let mut event_emitter = event_bus.emitter(); // Add/reset physics state components @@ -785,9 +782,5 @@ impl<'a> VSystem<'a> for Sys { land_on_grounds.into_iter().for_each(|(entity, vel)| { event_emitter.emit(ServerEvent::LandOnGround { entity, vel: vel.0 }); }); - sys_metrics.phys_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/common/sys/src/projectile.rs b/common/sys/src/projectile.rs index ed9cd79abe..27bfb73da6 100644 --- a/common/sys/src/projectile.rs +++ b/common/sys/src/projectile.rs @@ -5,7 +5,6 @@ use common::{ Stats, Vel, }, event::{EventBus, ServerEvent}, - metrics::SysMetrics, resources::DeltaTime, uid::UidAllocator, util::Dir, @@ -13,8 +12,8 @@ use common::{ GroupTarget, }; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, - SystemData, World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, + World, WriteStorage, }; use std::time::Duration; @@ -24,7 +23,6 @@ pub struct ReadData<'a> { dt: Read<'a, DeltaTime>, uid_allocator: Read<'a, UidAllocator>, server_bus: Read<'a, EventBus>, - metrics: ReadExpect<'a, SysMetrics>, positions: ReadStorage<'a, Pos>, physics_states: ReadStorage<'a, PhysicsState>, velocities: ReadStorage<'a, Vel>, @@ -52,7 +50,6 @@ impl<'a> VSystem<'a> for Sys { _job: &mut VJob, (read_data, mut orientations, mut projectiles): Self::SystemData, ) { - let start_time = std::time::Instant::now(); let mut server_emitter = read_data.server_bus.emitter(); // Attacks @@ -211,9 +208,5 @@ impl<'a> VSystem<'a> for Sys { .checked_sub(Duration::from_secs_f32(read_data.dt.0)) .unwrap_or_default(); } - read_data.metrics.projectile_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index 1f900819b0..955a642735 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -5,7 +5,6 @@ use common::{ PoiseChange, PoiseSource, Pos, Stats, }, event::{EventBus, ServerEvent}, - metrics::SysMetrics, outcome::Outcome, resources::{DeltaTime, Time}, uid::Uid, @@ -13,8 +12,7 @@ use common::{ }; use hashbrown::HashSet; use specs::{ - shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, Write, - WriteStorage, + shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, World, Write, WriteStorage, }; use vek::Vec3; @@ -28,7 +26,6 @@ pub struct ReadData<'a> { dt: Read<'a, DeltaTime>, time: Read<'a, Time>, server_bus: Read<'a, EventBus>, - metrics: ReadExpect<'a, SysMetrics>, positions: ReadStorage<'a, Pos>, uids: ReadStorage<'a, Uid>, bodies: ReadStorage<'a, Body>, @@ -66,7 +63,6 @@ impl<'a> VSystem<'a> for Sys { mut outcomes, ): Self::SystemData, ) { - let start_time = std::time::Instant::now(); let mut server_event_emitter = read_data.server_bus.emitter(); let dt = read_data.dt.0; @@ -270,10 +266,5 @@ impl<'a> VSystem<'a> for Sys { combo.reset(); } } - - read_data.metrics.stats_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 8e41ff8b89..acf9d5dfea 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -79,7 +79,7 @@ use common_net::{ use common_sys::plugin::PluginMgr; use common_sys::{plugin::memory_manager::EcsWorld, state::State}; use hashbrown::HashMap; -use metrics::{PhysicsMetrics, PlayerMetrics, StateTickMetrics, TickMetrics}; +use metrics::{EcsSystemMetrics, PhysicsMetrics, PlayerMetrics, TickMetrics}; use network::{Network, Pid, ProtocolAddr}; use persistence::{ character_loader::{CharacterLoader, CharacterLoaderResponseKind}, @@ -118,6 +118,10 @@ struct SpawnPoint(Vec3); #[derive(Copy, Clone, Default)] pub struct Tick(u64); +// Start of Tick, used for metrics +#[derive(Copy, Clone)] +pub struct TickStart(Instant); + pub struct Server { state: State, world: Arc, @@ -129,9 +133,6 @@ pub struct Server { runtime: Arc, metrics_shutdown: Arc, - tick_metrics: TickMetrics, - state_tick_metrics: StateTickMetrics, - physics_metrics: PhysicsMetrics, } impl Server { @@ -163,6 +164,10 @@ impl Server { let (network_request_metrics, registry_network) = metrics::NetworkRequestMetrics::new().unwrap(); let (player_metrics, registry_player) = metrics::PlayerMetrics::new().unwrap(); + let (ecs_system_metrics, registry_state) = EcsSystemMetrics::new().unwrap(); + let (tick_metrics, registry_tick) = + TickMetrics::new().expect("Failed to initialize server tick metrics submodule."); + let (physics_metrics, registry_physics) = PhysicsMetrics::new().unwrap(); let mut state = State::server(); state.ecs_mut().insert(settings.clone()); @@ -175,8 +180,12 @@ impl Server { .ecs_mut() .insert(LoginProvider::new(settings.auth_server_address.clone())); state.ecs_mut().insert(Tick(0)); + state.ecs_mut().insert(TickStart(Instant::now())); state.ecs_mut().insert(network_request_metrics); state.ecs_mut().insert(player_metrics); + state.ecs_mut().insert(ecs_system_metrics); + state.ecs_mut().insert(tick_metrics); + state.ecs_mut().insert(physics_metrics); state .ecs_mut() .insert(ChunkGenerator::new(chunk_gen_metrics)); @@ -196,23 +205,6 @@ impl Server { .ecs_mut() .insert(CharacterLoader::new(&persistence_db_dir)?); - // System timers for performance monitoring - state.ecs_mut().insert(sys::EntitySyncTimer::default()); - state.ecs_mut().insert(sys::GeneralMsgTimer::default()); - state.ecs_mut().insert(sys::PingMsgTimer::default()); - state - .ecs_mut() - .insert(sys::CharacterScreenMsgTimer::default()); - state.ecs_mut().insert(sys::InGameMsgTimer::default()); - state.ecs_mut().insert(sys::SentinelTimer::default()); - state.ecs_mut().insert(sys::SubscriptionTimer::default()); - state.ecs_mut().insert(sys::TerrainSyncTimer::default()); - state.ecs_mut().insert(sys::TerrainTimer::default()); - state.ecs_mut().insert(sys::WaypointTimer::default()); - state.ecs_mut().insert(sys::InviteTimeoutTimer::default()); - state.ecs_mut().insert(sys::PersistenceTimer::default()); - state.ecs_mut().insert(sys::AgentTimer::default()); - // System schedulers to control execution of systems state .ecs_mut() @@ -358,11 +350,6 @@ impl Server { state.ecs_mut().insert(DeletedEntities::default()); // register all metrics submodules here - let (tick_metrics, registry_tick) = - TickMetrics::new().expect("Failed to initialize server tick metrics submodule."); - let (state_tick_metrics, registry_state) = StateTickMetrics::new().unwrap(); - let (physics_metrics, registry_physics) = PhysicsMetrics::new().unwrap(); - let registry = Arc::new(Registry::new()); registry_chunk(®istry).expect("failed to register chunk gen metrics"); registry_network(®istry).expect("failed to register network request metrics"); @@ -403,9 +390,6 @@ impl Server { runtime, metrics_shutdown, - tick_metrics, - state_tick_metrics, - physics_metrics, }; debug!(?settings, "created veloren server with"); @@ -473,6 +457,8 @@ impl Server { /// the given duration. pub fn tick(&mut self, _input: Input, dt: Duration) -> Result, Error> { self.state.ecs().write_resource::().0 += 1; + self.state.ecs().write_resource::().0 = Instant::now(); + // This tick function is the centre of the Veloren universe. Most server-side // things are managed from here, and as such it's important that it // stays organised. Please consult the core developers before making @@ -705,236 +691,29 @@ impl Server { let end_of_server_tick = Instant::now(); // 8) Update Metrics - // Get system timing info + run_now::(&self.state.ecs()); { - let lock = self - .state - .ecs() - .read_resource::(); - let state = lock.stats.lock().unwrap(); - for (name, stat) in common::vsystem::gen_stats(&state, before_new_connections, 8, 8) { - self.tick_metrics - .system_start_time - .with_label_values(&[&name]) - .set(stat.start_ns() as i64); - self.tick_metrics - .system_length_time - .with_label_values(&[&name]) - .set(stat.length_ns() as i64); - self.tick_metrics - .system_thread_avg - .with_label_values(&[&name]) - .set(stat.avg_threads() as f64); - } + // Report timing info + let tick_metrics = self.state.ecs().read_resource::(); + + let tt = &tick_metrics.tick_time; + tt.with_label_values(&["new connections"]) + .set((before_message_system - before_new_connections).as_nanos() as i64); + tt.with_label_values(&["handle server events"]) + .set((before_update_terrain_and_regions - before_handle_events).as_nanos() as i64); + tt.with_label_values(&["update terrain and region map"]) + .set((before_sync - before_update_terrain_and_regions).as_nanos() as i64); + tt.with_label_values(&["state"]) + .set((before_handle_events - before_state_tick).as_nanos() as i64); + tt.with_label_values(&["world tick"]) + .set((before_entity_cleanup - before_world_tick).as_nanos() as i64); + tt.with_label_values(&["entity cleanup"]) + .set((before_persistence_updates - before_entity_cleanup).as_nanos() as i64); + tt.with_label_values(&["persistence_updates"]) + .set((end_of_server_tick - before_persistence_updates).as_nanos() as i64); } - let agent_nanos = self.state.ecs().read_resource::().nanos as i64; - let entity_sync_nanos = self - .state - .ecs() - .read_resource::() - .nanos as i64; - let message_nanos = { - let state = self.state.ecs(); - (state.read_resource::().nanos - + state.read_resource::().nanos - + state.read_resource::().nanos - + state.read_resource::().nanos) as i64 - }; - let sentinel_nanos = self.state.ecs().read_resource::().nanos as i64; - let subscription_nanos = self - .state - .ecs() - .read_resource::() - .nanos as i64; - let terrain_sync_nanos = self - .state - .ecs() - .read_resource::() - .nanos as i64; - let terrain_nanos = self.state.ecs().read_resource::().nanos as i64; - let waypoint_nanos = self.state.ecs().read_resource::().nanos as i64; - let invite_timeout_nanos = self - .state - .ecs() - .read_resource::() - .nanos as i64; - let stats_persistence_nanos = self - .state - .ecs() - .read_resource::() - .nanos as i64; - let total_sys_ran_in_dispatcher_nanos = - terrain_nanos + waypoint_nanos + invite_timeout_nanos + stats_persistence_nanos; - - // Report timing info - self.tick_metrics - .tick_time - .with_label_values(&["new connections"]) - .set((before_message_system - before_new_connections).as_nanos() as i64); - self.tick_metrics - .tick_time - .with_label_values(&["state tick"]) - .set( - (before_handle_events - before_state_tick).as_nanos() as i64 - - total_sys_ran_in_dispatcher_nanos, - ); - self.tick_metrics - .tick_time - .with_label_values(&["handle server events"]) - .set((before_update_terrain_and_regions - before_handle_events).as_nanos() as i64); - self.tick_metrics - .tick_time - .with_label_values(&["update terrain and region map"]) - .set((before_sync - before_update_terrain_and_regions).as_nanos() as i64); - self.tick_metrics - .tick_time - .with_label_values(&["world tick"]) - .set((before_entity_cleanup - before_world_tick).as_nanos() as i64); - self.tick_metrics - .tick_time - .with_label_values(&["entity cleanup"]) - .set((before_persistence_updates - before_entity_cleanup).as_nanos() as i64); - self.tick_metrics - .tick_time - .with_label_values(&["persistence_updates"]) - .set((end_of_server_tick - before_persistence_updates).as_nanos() as i64); - self.tick_metrics - .tick_time - .with_label_values(&["entity sync"]) - .set(entity_sync_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["message"]) - .set(message_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["sentinel"]) - .set(sentinel_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["subscription"]) - .set(subscription_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["terrain sync"]) - .set(terrain_sync_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["terrain"]) - .set(terrain_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["waypoint"]) - .set(waypoint_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["invite timeout"]) - .set(invite_timeout_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["persistence:stats"]) - .set(stats_persistence_nanos); - self.tick_metrics - .tick_time - .with_label_values(&["agent"]) - .set(agent_nanos); - - //detailed state metrics - { - /* - let res = self - .state - .ecs() - .read_resource::(); - let c = &self.state_tick_metrics.state_tick_time_count; - let agent_ns = res.agent_ns.load(Ordering::Relaxed); - let mount_ns = res.mount_ns.load(Ordering::Relaxed); - let controller_ns = res.controller_ns.load(Ordering::Relaxed); - let character_behavior_ns = res.character_behavior_ns.load(Ordering::Relaxed); - let stats_ns = res.stats_ns.load(Ordering::Relaxed); - let phys_ns = res.phys_ns.load(Ordering::Relaxed); - let projectile_ns = res.projectile_ns.load(Ordering::Relaxed); - let melee_ns = res.melee_ns.load(Ordering::Relaxed); - - c.with_label_values(&[sys::AGENT_SYS]).inc_by(agent_ns); - c.with_label_values(&[common_sys::]) - .inc_by(mount_ns); - c.with_label_values(&[common_sys::CONTROLLER_SYS]) - .inc_by(controller_ns); - c.with_label_values(&[common_sys::CHARACTER_BEHAVIOR_SYS]) - .inc_by(character_behavior_ns); - c.with_label_values(&[common_sys::STATS_SYS]) - .inc_by(stats_ns); - c.with_label_values(&[common_sys::PHYS_SYS]).inc_by(phys_ns); - c.with_label_values(&[common_sys::PROJECTILE_SYS]) - .inc_by(projectile_ns); - c.with_label_values(&[common_sys::MELEE_SYS]) - .inc_by(melee_ns); - - const NANOSEC_PER_SEC: f64 = Duration::from_secs(1).as_nanos() as f64; - let h = &self.state_tick_metrics.state_tick_time_hist; - h.with_label_values(&[sys::AGENT_SYS]) - .observe(agent_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::MOUNT_SYS]) - .observe(mount_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::CONTROLLER_SYS]) - .observe(controller_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::CHARACTER_BEHAVIOR_SYS]) - .observe(character_behavior_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::STATS_SYS]) - .observe(stats_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::PHYS_SYS]) - .observe(phys_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::PROJECTILE_SYS]) - .observe(projectile_ns as f64 / NANOSEC_PER_SEC); - h.with_label_values(&[common_sys::MELEE_SYS]) - .observe(melee_ns as f64 / NANOSEC_PER_SEC); - */ - } - - //detailed physics metrics - { - let res = self - .state - .ecs() - .read_resource::(); - - self.physics_metrics - .entity_entity_collision_checks_count - .inc_by(res.entity_entity_collision_checks); - self.physics_metrics - .entity_entity_collisions_count - .inc_by(res.entity_entity_collisions); - } - - // Report other info - self.tick_metrics - .time_of_day - .set(self.state.ecs().read_resource::().0); - if self.tick_metrics.is_100th_tick() { - let mut chonk_cnt = 0; - let mut group_cnt = 0; - let chunk_cnt = self.state.terrain().iter().fold(0, |a, (_, c)| { - chonk_cnt += 1; - group_cnt += c.sub_chunk_groups(); - a + c.sub_chunks_len() - }); - self.tick_metrics.chonks_count.set(chonk_cnt as i64); - self.tick_metrics.chunks_count.set(chunk_cnt as i64); - self.tick_metrics.chunk_groups_count.set(group_cnt as i64); - - let entity_count = self.state.ecs().entities().join().count(); - self.tick_metrics.entity_count.set(entity_count as i64); - } - //self.metrics.entity_count.set(self.state.); - self.tick_metrics - .tick_time - .with_label_values(&["metrics"]) - .set(end_of_server_tick.elapsed().as_nanos() as i64); - self.tick_metrics.tick(); - // 9) Finish the tick, pass control back to the frontend. Ok(frontend_events) diff --git a/server/src/metrics.rs b/server/src/metrics.rs index 622cd4006c..4f7a7e60a6 100644 --- a/server/src/metrics.rs +++ b/server/src/metrics.rs @@ -5,10 +5,6 @@ use prometheus::{ use std::{ convert::TryInto, error::Error, - sync::{ - atomic::{AtomicU64, Ordering}, - Arc, - }, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -19,11 +15,15 @@ pub struct PhysicsMetrics { pub entity_entity_collisions_count: IntCounter, } -pub struct StateTickMetrics { - // Counter will only give us granularity on pool speed (2s?) for actuall spike detection we +pub struct EcsSystemMetrics { + // Gauges give us detailed information for random ticks + pub system_start_time: IntGaugeVec, + pub system_length_time: IntGaugeVec, + pub system_thread_avg: GaugeVec, + // Counter will only give us granularity on pool speed (2s?) for actual spike detection we // need the Historgram - pub state_tick_time_hist: HistogramVec, - pub state_tick_time_count: IntCounterVec, + pub system_length_hist: HistogramVec, + pub system_length_count: IntCounterVec, } pub struct PlayerMetrics { @@ -54,10 +54,6 @@ pub struct TickMetrics { pub start_time: IntGauge, pub time_of_day: Gauge, pub light_count: IntGauge, - pub system_start_time: IntGaugeVec, - pub system_length_time: IntGaugeVec, - pub system_thread_avg: GaugeVec, - tick: Arc, } impl PhysicsMetrics { @@ -91,7 +87,7 @@ impl PhysicsMetrics { } } -impl StateTickMetrics { +impl EcsSystemMetrics { pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> { let bucket = vec![ Duration::from_micros(1).as_secs_f64(), @@ -107,7 +103,7 @@ impl StateTickMetrics { Duration::from_millis(50).as_secs_f64(), Duration::from_millis(100).as_secs_f64(), ]; - let state_tick_time_hist = HistogramVec::new( + let system_length_hist = HistogramVec::new( HistogramOpts::new( "state_tick_time_hist", "shows the number of clients joined to the server", @@ -115,27 +111,54 @@ impl StateTickMetrics { .buckets(bucket), &["system"], )?; - let state_tick_time_count = IntCounterVec::new( + let system_length_count = IntCounterVec::new( Opts::new( "state_tick_time_count", "shows the detailed time inside the `state_tick` for each system", ), &["system"], )?; + let system_start_time = IntGaugeVec::new( + Opts::new( + "system_start_time", + "start relative to tick start in ns required per ECS system", + ), + &["system"], + )?; + let system_length_time = IntGaugeVec::new( + Opts::new("system_length_time", "time in ns required per ECS system"), + &["system"], + )?; + let system_thread_avg = GaugeVec::new( + Opts::new( + "system_thread_avg", + "average threads used by the ECS system", + ), + &["system"], + )?; - let state_tick_time_hist_clone = state_tick_time_hist.clone(); - let state_tick_time_count_clone = state_tick_time_count.clone(); + let system_length_hist_clone = system_length_hist.clone(); + let system_length_count_clone = system_length_count.clone(); + let system_start_time_clone = system_start_time.clone(); + let system_length_time_clone = system_length_time.clone(); + let system_thread_avg_clone = system_thread_avg.clone(); let f = |registry: &Registry| { - registry.register(Box::new(state_tick_time_hist_clone))?; - registry.register(Box::new(state_tick_time_count_clone))?; + registry.register(Box::new(system_length_hist_clone))?; + registry.register(Box::new(system_length_count_clone))?; + registry.register(Box::new(system_start_time_clone))?; + registry.register(Box::new(system_length_time_clone))?; + registry.register(Box::new(system_thread_avg_clone))?; Ok(()) }; Ok(( Self { - state_tick_time_hist, - state_tick_time_count, + system_length_hist, + system_length_count, + system_start_time, + system_length_time, + system_thread_avg, }, Box::new(f), )) @@ -293,24 +316,6 @@ impl TickMetrics { Opts::new("tick_time", "time in ns required for a tick of the server"), &["period"], )?; - let system_start_time = IntGaugeVec::new( - Opts::new( - "system_start_time", - "start relative to tick start in ns required per ECS system", - ), - &["system"], - )?; - let system_length_time = IntGaugeVec::new( - Opts::new("system_length_time", "time in ns required per ECS system"), - &["system"], - )?; - let system_thread_avg = GaugeVec::new( - Opts::new( - "system_thread_avg", - "average threads used by the ECS system", - ), - &["system"], - )?; let since_the_epoch = SystemTime::now() .duration_since(UNIX_EPOCH) @@ -326,10 +331,6 @@ impl TickMetrics { let time_of_day_clone = time_of_day.clone(); let light_count_clone = light_count.clone(); let tick_time_clone = tick_time.clone(); - let tick = Arc::new(AtomicU64::new(0)); - let system_start_time_clone = system_start_time.clone(); - let system_length_time_clone = system_length_time.clone(); - let system_thread_avg_clone = system_thread_avg.clone(); let f = |registry: &Registry| { registry.register(Box::new(chonks_count_clone))?; @@ -341,9 +342,6 @@ impl TickMetrics { registry.register(Box::new(time_of_day_clone))?; registry.register(Box::new(light_count_clone))?; registry.register(Box::new(tick_time_clone))?; - registry.register(Box::new(system_start_time_clone))?; - registry.register(Box::new(system_length_time_clone))?; - registry.register(Box::new(system_thread_avg_clone))?; Ok(()) }; @@ -358,16 +356,8 @@ impl TickMetrics { start_time, time_of_day, light_count, - system_start_time, - system_length_time, - system_thread_avg, - tick, }, Box::new(f), )) } - - pub fn tick(&self) { self.tick.fetch_add(1, Ordering::Relaxed); } - - pub fn is_100th_tick(&self) -> bool { self.tick.load(Ordering::Relaxed).rem_euclid(100) == 0 } } diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index b883765eba..d67d9a448e 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -1,4 +1,3 @@ -use super::SysTimer; use common::{ comp::{ self, @@ -16,7 +15,6 @@ use common::{ UnresolvedChatMsg, Vel, }, event::{Emitter, EventBus, ServerEvent}, - metrics::SysMetrics, path::TraversalConfig, resources::{DeltaTime, TimeOfDay}, terrain::{Block, TerrainGrid}, @@ -64,7 +62,6 @@ pub struct ReadData<'a> { uid_allocator: Read<'a, UidAllocator>, dt: Read<'a, DeltaTime>, group_manager: Read<'a, group::GroupManager>, - sys_metrics: ReadExpect<'a, SysMetrics>, energies: ReadStorage<'a, Energy>, positions: ReadStorage<'a, Pos>, velocities: ReadStorage<'a, Vel>, @@ -105,7 +102,6 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, - Write<'a, SysTimer>, Write<'a, EventBus>, WriteStorage<'a, Agent>, WriteStorage<'a, Controller>, @@ -118,11 +114,8 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 fn run( _job: &mut VJob, - (read_data, mut sys_timer, event_bus, mut agents, mut controllers): Self::SystemData, + (read_data, event_bus, mut agents, mut controllers): Self::SystemData, ) { - let start_time = std::time::Instant::now(); - sys_timer.start(); - ( &read_data.entities, (&read_data.energies, &read_data.healths), @@ -427,13 +420,6 @@ impl<'a> VSystem<'a> for Sys { debug_assert!(controller.inputs.look_dir.map(|e| !e.is_nan()).reduce_and()); }, ); - - read_data.sys_metrics.agent_ns.store( - start_time.elapsed().as_nanos() as u64, - std::sync::atomic::Ordering::Relaxed, - ); - - sys_timer.end(); } } diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index f48fa6ce42..43903b84ba 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -1,7 +1,4 @@ -use super::{ - sentinel::{DeletedEntities, ReadTrackers, TrackedComps}, - SysTimer, -}; +use super::sentinel::{DeletedEntities, ReadTrackers, TrackedComps}; use crate::{ client::Client, presence::{Presence, RegionSubscription}, @@ -27,13 +24,12 @@ use vek::*; #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, Read<'a, Tick>, ReadExpect<'a, TimeOfDay>, ReadExpect<'a, RegionMap>, - Write<'a, SysTimer>, ReadStorage<'a, Uid>, ReadStorage<'a, Pos>, ReadStorage<'a, Vel>, @@ -64,7 +60,6 @@ impl<'a> VSystem<'a> for Sys { tick, time_of_day, region_map, - mut timer, uids, positions, velocities, @@ -84,8 +79,6 @@ impl<'a> VSystem<'a> for Sys { trackers, ): Self::SystemData, ) { - timer.start(); - let tick = tick.0; // To send entity updates // 1. Iterate through regions @@ -385,7 +378,5 @@ impl<'a> VSystem<'a> for Sys { } tof_lazymsg.as_ref().map(|msg| client.send_prepared(&msg)); } - - timer.end(); } } diff --git a/server/src/sys/invite_timeout.rs b/server/src/sys/invite_timeout.rs index 37fd4bbc0f..ed155d3bf3 100644 --- a/server/src/sys/invite_timeout.rs +++ b/server/src/sys/invite_timeout.rs @@ -1,4 +1,3 @@ -use super::SysTimer; use crate::client::Client; use common::{ comp::invite::{Invite, PendingInvites}, @@ -6,20 +5,19 @@ use common::{ vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{InviteAnswer, ServerGeneral}; -use specs::{Entities, Join, ReadStorage, Write, WriteStorage}; +use specs::{Entities, Join, ReadStorage, WriteStorage}; /// This system removes timed out invites #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, WriteStorage<'a, Invite>, WriteStorage<'a, PendingInvites>, ReadStorage<'a, Client>, ReadStorage<'a, Uid>, - Write<'a, SysTimer>, ); const NAME: &'static str = "invite_timeout"; @@ -28,12 +26,9 @@ impl<'a> VSystem<'a> for Sys { fn run( _job: &mut VJob, - (entities, mut invites, mut pending_invites, clients, uids, mut timer): Self::SystemData, + (entities, mut invites, mut pending_invites, clients, uids): Self::SystemData, ) { - timer.start(); - let now = std::time::Instant::now(); - let timed_out_invites = (&entities, &invites) .join() .filter_map(|(invitee, Invite { inviter, kind })| { @@ -72,7 +67,5 @@ impl<'a> VSystem<'a> for Sys { for entity in timed_out_invites { invites.remove(entity); } - - timer.end(); } } diff --git a/server/src/sys/metrics.rs b/server/src/sys/metrics.rs new file mode 100644 index 0000000000..60d7c2d5d0 --- /dev/null +++ b/server/src/sys/metrics.rs @@ -0,0 +1,128 @@ +use crate::{ + metrics::{EcsSystemMetrics, PhysicsMetrics, TickMetrics}, + Tick, TickStart, +}; +use common::{ + metrics::SysMetrics, + resources::TimeOfDay, + terrain::TerrainGrid, + vsystem::{Origin, Phase, VJob, VSystem}, +}; +use specs::{Entities, Join, Read, ReadExpect}; +use std::time::Instant; + +/// This system exports metrics +#[derive(Default)] +pub struct Sys; +impl<'a> VSystem<'a> for Sys { + #[allow(clippy::type_complexity)] + type SystemData = ( + Option>, + ReadExpect<'a, Tick>, + ReadExpect<'a, TimeOfDay>, + ReadExpect<'a, TickStart>, + Option>, + Read<'a, SysMetrics>, + Read<'a, common::metrics::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 VJob, + ( + entities, + 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::vsystem::gen_stats(&state, tick_start.0, 8, 8) { + 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() as i64; + export_ecs + .system_length_time + .with_label_values(&[&name]) + .set(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); + } + } + + //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 i64; + export_ecs + .system_length_time + .with_label_values(&["metrics"]) + .set(len); + export_ecs + .system_length_hist + .with_label_values(&["metrics"]) + .observe(len as f64 / NANOSEC_PER_SEC); + } +} diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index bbd6a258e3..594b8c9be3 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -1,6 +1,7 @@ pub mod agent; pub mod entity_sync; pub mod invite_timeout; +pub mod metrics; pub mod msg; pub mod object; pub mod persistence; @@ -17,20 +18,7 @@ use std::{ time::{Duration, Instant}, }; -pub type EntitySyncTimer = SysTimer; -pub type GeneralMsgTimer = SysTimer; -pub type PingMsgTimer = SysTimer; -pub type CharacterScreenMsgTimer = SysTimer; -pub type InGameMsgTimer = SysTimer; -pub type SentinelTimer = SysTimer; -pub type SubscriptionTimer = SysTimer; -pub type TerrainTimer = SysTimer; -pub type TerrainSyncTimer = SysTimer; -pub type WaypointTimer = SysTimer; -pub type InviteTimeoutTimer = SysTimer; -pub type PersistenceTimer = SysTimer; pub type PersistenceScheduler = SysScheduler; -pub type AgentTimer = SysTimer; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch::(dispatch_builder, &[]); @@ -87,38 +75,3 @@ impl Default for SysScheduler { } } } - -/// Used to keep track of how much time each system takes -pub struct SysTimer { - pub nanos: u64, - start: Option, - _phantom: PhantomData, -} - -impl SysTimer { - pub fn start(&mut self) { - if self.start.is_some() { - panic!("Timer already started"); - } - self.start = Some(Instant::now()); - } - - pub fn end(&mut self) { - self.nanos = self - .start - .take() - .expect("Timer ended without starting it") - .elapsed() - .as_nanos() as u64; - } -} - -impl Default for SysTimer { - fn default() -> Self { - Self { - nanos: 0, - start: None, - _phantom: PhantomData, - } - } -} diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index e3b8b8e1b2..1ef07dfc19 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -1,4 +1,3 @@ -use super::super::SysTimer; use crate::{ alias_validator::AliasValidator, character_creator, client::Client, persistence::character_loader::CharacterLoader, presence::Presence, EditableSettings, @@ -10,7 +9,7 @@ use common::{ vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ClientGeneral, ServerGeneral}; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage}; use std::sync::atomic::Ordering; use tracing::{debug, warn}; @@ -129,7 +128,6 @@ impl<'a> VSystem<'a> for Sys { Entities<'a>, Read<'a, EventBus>, ReadExpect<'a, CharacterLoader>, - Write<'a, SysTimer>, ReadStorage<'a, Uid>, ReadStorage<'a, Client>, ReadStorage<'a, Player>, @@ -148,7 +146,6 @@ impl<'a> VSystem<'a> for Sys { entities, server_event_bus, character_loader, - mut timer, uids, clients, players, @@ -157,8 +154,6 @@ impl<'a> VSystem<'a> for Sys { alias_validator, ): Self::SystemData, ) { - timer.start(); - let mut server_emitter = server_event_bus.emitter(); let mut new_chat_msgs = Vec::new(); @@ -193,7 +188,5 @@ impl<'a> VSystem<'a> for Sys { server_emitter.emit(ServerEvent::Chat(msg)); } } - - timer.end() } } diff --git a/server/src/sys/msg/general.rs b/server/src/sys/msg/general.rs index d928fea9b9..9da374a9d5 100644 --- a/server/src/sys/msg/general.rs +++ b/server/src/sys/msg/general.rs @@ -1,4 +1,3 @@ -use super::super::SysTimer; use crate::{client::Client, metrics::PlayerMetrics}; use common::{ comp::{ChatMode, Player, UnresolvedChatMsg}, @@ -10,7 +9,7 @@ use common::{ use common_net::msg::{ validate_chat_msg, ChatMsgValidationError, ClientGeneral, MAX_BYTES_CHAT_MSG, }; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage}; use std::sync::atomic::Ordering; use tracing::{debug, error, warn}; @@ -74,7 +73,6 @@ impl<'a> VSystem<'a> for Sys { Read<'a, EventBus>, Read<'a, Time>, ReadExpect<'a, PlayerMetrics>, - Write<'a, SysTimer>, ReadStorage<'a, Uid>, ReadStorage<'a, ChatMode>, ReadStorage<'a, Player>, @@ -92,15 +90,12 @@ impl<'a> VSystem<'a> for Sys { server_event_bus, time, player_metrics, - mut timer, uids, chat_modes, players, clients, ): Self::SystemData, ) { - timer.start(); - let mut server_emitter = server_event_bus.emitter(); let mut new_chat_msgs = Vec::new(); @@ -138,7 +133,5 @@ impl<'a> VSystem<'a> for Sys { server_emitter.emit(ServerEvent::Chat(msg)); } } - - timer.end() } } diff --git a/server/src/sys/msg/in_game.rs b/server/src/sys/msg/in_game.rs index 454436a9e3..e35359baa1 100644 --- a/server/src/sys/msg/in_game.rs +++ b/server/src/sys/msg/in_game.rs @@ -1,4 +1,3 @@ -use super::super::SysTimer; use crate::{client::Client, metrics::NetworkRequestMetrics, presence::Presence, Settings}; use common::{ comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, Stats, Vel}, @@ -174,7 +173,6 @@ impl<'a> VSystem<'a> for Sys { Read<'a, EventBus>, ReadExpect<'a, TerrainGrid>, ReadExpect<'a, NetworkRequestMetrics>, - Write<'a, SysTimer>, ReadStorage<'a, CanBuild>, ReadStorage<'a, ForceUpdate>, WriteStorage<'a, Stats>, @@ -200,7 +198,6 @@ impl<'a> VSystem<'a> for Sys { server_event_bus, terrain, network_metrics, - mut timer, can_build, force_updates, mut stats, @@ -215,8 +212,6 @@ impl<'a> VSystem<'a> for Sys { settings, ): Self::SystemData, ) { - timer.start(); - let mut server_emitter = server_event_bus.emitter(); for (entity, client, mut maybe_presence) in @@ -244,7 +239,5 @@ impl<'a> VSystem<'a> for Sys { ) }); } - - timer.end() } } diff --git a/server/src/sys/msg/ping.rs b/server/src/sys/msg/ping.rs index a80ee2799a..90251c34fb 100644 --- a/server/src/sys/msg/ping.rs +++ b/server/src/sys/msg/ping.rs @@ -1,4 +1,3 @@ -use super::super::SysTimer; use crate::{client::Client, metrics::PlayerMetrics, Settings}; use common::{ event::{EventBus, ServerEvent}, @@ -6,7 +5,7 @@ use common::{ vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::PingMsg; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage}; use std::sync::atomic::Ordering; use tracing::{debug, info}; @@ -30,7 +29,6 @@ impl<'a> VSystem<'a> for Sys { Read<'a, EventBus>, Read<'a, Time>, ReadExpect<'a, PlayerMetrics>, - Write<'a, SysTimer>, ReadStorage<'a, Client>, Read<'a, Settings>, ); @@ -41,18 +39,8 @@ impl<'a> VSystem<'a> for Sys { fn run( _job: &mut VJob, - ( - entities, - server_event_bus, - time, - player_metrics, - mut timer, - clients, - settings, - ): Self::SystemData, + (entities, server_event_bus, time, player_metrics, clients, settings): Self::SystemData, ) { - timer.start(); - let mut server_emitter = server_event_bus.emitter(); for (entity, client) in (&entities, &clients).join() { @@ -93,7 +81,5 @@ impl<'a> VSystem<'a> for Sys { }, } } - - timer.end() } } diff --git a/server/src/sys/persistence.rs b/server/src/sys/persistence.rs index 858b8a5cf1..9feaed9cec 100644 --- a/server/src/sys/persistence.rs +++ b/server/src/sys/persistence.rs @@ -1,8 +1,4 @@ -use crate::{ - persistence::character_updater, - presence::Presence, - sys::{SysScheduler, SysTimer}, -}; +use crate::{persistence::character_updater, presence::Presence, sys::SysScheduler}; use common::{ comp::{Inventory, Stats, Waypoint}, vsystem::{Origin, Phase, VJob, VSystem}, @@ -14,7 +10,7 @@ use specs::{Join, ReadExpect, ReadStorage, Write}; pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( ReadStorage<'a, Presence>, ReadStorage<'a, Stats>, @@ -22,7 +18,6 @@ impl<'a> VSystem<'a> for Sys { ReadStorage<'a, Waypoint>, ReadExpect<'a, character_updater::CharacterUpdater>, Write<'a, SysScheduler>, - Write<'a, SysTimer>, ); const NAME: &'static str = "persistence"; @@ -38,11 +33,9 @@ impl<'a> VSystem<'a> for Sys { player_waypoint, updater, mut scheduler, - mut timer, ): Self::SystemData, ) { if scheduler.should_run() { - timer.start(); updater.batch_update( ( &presences, @@ -58,7 +51,6 @@ impl<'a> VSystem<'a> for Sys { }, ), ); - timer.end(); } } } diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index f6c9c38aaf..fab165a31e 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -1,4 +1,3 @@ -use super::SysTimer; use common::{ comp::{ Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Combo, Energy, @@ -15,7 +14,7 @@ use common_net::{ use hashbrown::HashMap; use specs::{ shred::ResourceId, Entity as EcsEntity, Join, ReadExpect, ReadStorage, SystemData, World, - Write, WriteExpect, + WriteExpect, }; use vek::*; @@ -25,22 +24,14 @@ use vek::*; #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - type SystemData = ( - Write<'a, SysTimer>, - TrackedComps<'a>, - WriteTrackers<'a>, - ); + type SystemData = (TrackedComps<'a>, WriteTrackers<'a>); const NAME: &'static str = "sentinel"; const ORIGIN: Origin = Origin::Server; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (mut timer, comps, mut trackers): Self::SystemData) { - timer.start(); - + fn run(_job: &mut VJob, (comps, mut trackers): Self::SystemData) { record_changes(&comps, &mut trackers); - - timer.end(); } } diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index e8ad98aec4..8dfda871c0 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -1,7 +1,4 @@ -use super::{ - sentinel::{DeletedEntities, TrackedComps}, - SysTimer, -}; +use super::sentinel::{DeletedEntities, TrackedComps}; use crate::{ client::Client, presence::{self, Presence, RegionSubscription}, @@ -25,11 +22,10 @@ use vek::*; #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, ReadExpect<'a, RegionMap>, - Write<'a, SysTimer>, ReadStorage<'a, Uid>, ReadStorage<'a, Pos>, ReadStorage<'a, Vel>, @@ -51,7 +47,6 @@ impl<'a> VSystem<'a> for Sys { ( entities, region_map, - mut timer, uids, positions, velocities, @@ -63,8 +58,6 @@ impl<'a> VSystem<'a> for Sys { tracked_comps, ): Self::SystemData, ) { - timer.start(); - // To update subscriptions // 1. Iterate through clients // 2. Calculate current chunk position @@ -212,8 +205,6 @@ impl<'a> VSystem<'a> for Sys { } } } - - timer.end(); } } diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index e99e4a4ca7..f24495dda2 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -1,4 +1,3 @@ -use super::SysTimer; use crate::{ chunk_generator::ChunkGenerator, client::Client, presence::Presence, rtsim::RtSim, Tick, }; @@ -30,7 +29,6 @@ impl<'a> VSystem<'a> for Sys { type SystemData = ( Read<'a, EventBus>, Read<'a, Tick>, - Write<'a, SysTimer>, WriteExpect<'a, ChunkGenerator>, WriteExpect<'a, TerrainGrid>, Write<'a, TerrainChanges>, @@ -49,7 +47,6 @@ impl<'a> VSystem<'a> for Sys { ( server_event_bus, tick, - mut timer, mut chunk_generator, mut terrain, mut terrain_changes, @@ -59,8 +56,6 @@ impl<'a> VSystem<'a> for Sys { clients, ): Self::SystemData, ) { - timer.start(); - let mut server_emitter = server_event_bus.emitter(); // Fetch any generated `TerrainChunk`s and insert them into the terrain. @@ -240,8 +235,6 @@ impl<'a> VSystem<'a> for Sys { chunk_generator.cancel_if_pending(key); } - - timer.end() } } diff --git a/server/src/sys/terrain_sync.rs b/server/src/sys/terrain_sync.rs index 2e52332036..874186847c 100644 --- a/server/src/sys/terrain_sync.rs +++ b/server/src/sys/terrain_sync.rs @@ -1,4 +1,3 @@ -use super::SysTimer; use crate::{client::Client, presence::Presence}; use common::{ comp::Pos, @@ -7,18 +6,17 @@ use common::{ }; use common_net::msg::ServerGeneral; use common_sys::state::TerrainChanges; -use specs::{Join, Read, ReadExpect, ReadStorage, Write}; +use specs::{Join, Read, ReadExpect, ReadStorage}; /// This systems sends new chunks to clients as well as changes to existing /// chunks #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( ReadExpect<'a, TerrainGrid>, Read<'a, TerrainChanges>, - Write<'a, SysTimer>, ReadStorage<'a, Pos>, ReadStorage<'a, Presence>, ReadStorage<'a, Client>, @@ -30,10 +28,8 @@ impl<'a> VSystem<'a> for Sys { fn run( _job: &mut VJob, - (terrain, terrain_changes, mut timer, positions, presences, clients): Self::SystemData, + (terrain, terrain_changes, positions, presences, clients): Self::SystemData, ) { - timer.start(); - // Sync changed chunks 'chunk: for chunk_key in &terrain_changes.modified_chunks { let mut lazy_msg = None; @@ -66,7 +62,5 @@ impl<'a> VSystem<'a> for Sys { } lazy_msg.as_ref().map(|ref msg| client.send_prepared(&msg)); } - - timer.end(); } } diff --git a/server/src/sys/waypoint.rs b/server/src/sys/waypoint.rs index 7d261cc3be..05945179f2 100644 --- a/server/src/sys/waypoint.rs +++ b/server/src/sys/waypoint.rs @@ -1,4 +1,3 @@ -use super::SysTimer; use crate::client::Client; use common::{ comp::{Player, Pos, Waypoint, WaypointArea}, @@ -6,7 +5,7 @@ use common::{ vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{Notification, ServerGeneral}; -use specs::{Entities, Join, Read, ReadStorage, Write, WriteStorage}; +use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; /// Cooldown time (in seconds) for "Waypoint Saved" notifications const NOTIFY_TIME: f64 = 10.0; @@ -16,7 +15,7 @@ const NOTIFY_TIME: f64 = 10.0; #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, ReadStorage<'a, Pos>, @@ -25,7 +24,6 @@ impl<'a> VSystem<'a> for Sys { WriteStorage<'a, Waypoint>, ReadStorage<'a, Client>, Read<'a, Time>, - Write<'a, SysTimer>, ); const NAME: &'static str = "waypoint"; @@ -42,11 +40,8 @@ impl<'a> VSystem<'a> for Sys { mut waypoints, clients, time, - mut timer, ): Self::SystemData, ) { - timer.start(); - for (entity, player_pos, _, client) in (&entities, &positions, &players, &clients).join() { for (waypoint_pos, waypoint_area) in (&positions, &waypoint_areas).join() { if player_pos.0.distance_squared(waypoint_pos.0) < waypoint_area.radius().powi(2) { @@ -61,7 +56,5 @@ impl<'a> VSystem<'a> for Sys { } } } - - timer.end(); } } diff --git a/voxygen/src/ecs/sys/floater.rs b/voxygen/src/ecs/sys/floater.rs index 8e293ec2db..1fc849de7f 100644 --- a/voxygen/src/ecs/sys/floater.rs +++ b/voxygen/src/ecs/sys/floater.rs @@ -18,7 +18,7 @@ pub const HP_ACCUMULATETIME: f32 = 1.0; #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, ReadExpect<'a, MyEntity>, diff --git a/voxygen/src/ecs/sys/interpolation.rs b/voxygen/src/ecs/sys/interpolation.rs index 4bd1489230..34954612b4 100644 --- a/voxygen/src/ecs/sys/interpolation.rs +++ b/voxygen/src/ecs/sys/interpolation.rs @@ -12,7 +12,7 @@ use vek::*; #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { - #[allow(clippy::type_complexity)] // TODO: Pending review in #587 + #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, Read<'a, DeltaTime>, From ea94ca6656767dd0d3b4f05de150ce400dde1a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Mon, 8 Mar 2021 09:49:16 +0100 Subject: [PATCH 3/5] switch server to the new Registry struct, this gets rid of RegistryFn pattern and simplyfies stuff, its a result of the Prometheus-tracy crate --- server/src/lib.rs | 24 ++--- server/src/metrics.rs | 206 ++++++++++++++---------------------------- 2 files changed, 75 insertions(+), 155 deletions(-) diff --git a/server/src/lib.rs b/server/src/lib.rs index acf9d5dfea..8b83cf7e88 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -160,14 +160,13 @@ impl Server { panic!("Migration error: {:?}", e); } - let (chunk_gen_metrics, registry_chunk) = metrics::ChunkGenMetrics::new().unwrap(); - let (network_request_metrics, registry_network) = - metrics::NetworkRequestMetrics::new().unwrap(); - let (player_metrics, registry_player) = metrics::PlayerMetrics::new().unwrap(); - let (ecs_system_metrics, registry_state) = EcsSystemMetrics::new().unwrap(); - let (tick_metrics, registry_tick) = - TickMetrics::new().expect("Failed to initialize server tick metrics submodule."); - let (physics_metrics, registry_physics) = PhysicsMetrics::new().unwrap(); + let registry = Arc::new(Registry::new()); + let chunk_gen_metrics = metrics::ChunkGenMetrics::new(®istry).unwrap(); + let network_request_metrics = metrics::NetworkRequestMetrics::new(®istry).unwrap(); + let player_metrics = metrics::PlayerMetrics::new(®istry).unwrap(); + let ecs_system_metrics = EcsSystemMetrics::new(®istry).unwrap(); + let tick_metrics = TickMetrics::new(®istry).unwrap(); + let physics_metrics = PhysicsMetrics::new(®istry).unwrap(); let mut state = State::server(); state.ecs_mut().insert(settings.clone()); @@ -349,15 +348,6 @@ impl Server { state.ecs_mut().insert(DeletedEntities::default()); - // register all metrics submodules here - let registry = Arc::new(Registry::new()); - registry_chunk(®istry).expect("failed to register chunk gen metrics"); - registry_network(®istry).expect("failed to register network request metrics"); - registry_player(®istry).expect("failed to register player metrics"); - registry_tick(®istry).expect("failed to register tick metrics"); - registry_state(®istry).expect("failed to register state metrics"); - registry_physics(®istry).expect("failed to register state metrics"); - let network = Network::new_with_registry(Pid::new(), &runtime, ®istry); let metrics_shutdown = Arc::new(Notify::new()); let metrics_shutdown_clone = Arc::clone(&metrics_shutdown); diff --git a/server/src/metrics.rs b/server/src/metrics.rs index 4f7a7e60a6..596611cef8 100644 --- a/server/src/metrics.rs +++ b/server/src/metrics.rs @@ -8,8 +8,6 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -type RegistryFn = Box Result<(), prometheus::Error>>; - pub struct PhysicsMetrics { pub entity_entity_collision_checks_count: IntCounter, pub entity_entity_collisions_count: IntCounter, @@ -57,7 +55,7 @@ pub struct TickMetrics { } impl PhysicsMetrics { - pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> { + pub fn new(registry: &Registry) -> Result { let entity_entity_collision_checks_count = IntCounter::with_opts(Opts::new( "entity_entity_collision_checks_count", "shows the number of collision checks", @@ -67,28 +65,18 @@ impl PhysicsMetrics { "shows the number of actual collisions detected", ))?; - let entity_entity_collision_checks_count_clone = - entity_entity_collision_checks_count.clone(); - let entity_entity_collisions_count_clone = entity_entity_collisions_count.clone(); + registry.register(Box::new(entity_entity_collision_checks_count.clone()))?; + registry.register(Box::new(entity_entity_collisions_count.clone()))?; - let f = |registry: &Registry| { - registry.register(Box::new(entity_entity_collision_checks_count_clone))?; - registry.register(Box::new(entity_entity_collisions_count_clone))?; - Ok(()) - }; - - Ok(( - Self { - entity_entity_collision_checks_count, - entity_entity_collisions_count, - }, - Box::new(f), - )) + Ok(Self { + entity_entity_collision_checks_count, + entity_entity_collisions_count, + }) } } impl EcsSystemMetrics { - pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> { + pub fn new(registry: &Registry) -> Result { let bucket = vec![ Duration::from_micros(1).as_secs_f64(), Duration::from_micros(10).as_secs_f64(), @@ -137,36 +125,24 @@ impl EcsSystemMetrics { &["system"], )?; - let system_length_hist_clone = system_length_hist.clone(); - let system_length_count_clone = system_length_count.clone(); - let system_start_time_clone = system_start_time.clone(); - let system_length_time_clone = system_length_time.clone(); - let system_thread_avg_clone = system_thread_avg.clone(); + registry.register(Box::new(system_length_hist.clone()))?; + registry.register(Box::new(system_length_count.clone()))?; + registry.register(Box::new(system_start_time.clone()))?; + registry.register(Box::new(system_length_time.clone()))?; + registry.register(Box::new(system_thread_avg.clone()))?; - let f = |registry: &Registry| { - registry.register(Box::new(system_length_hist_clone))?; - registry.register(Box::new(system_length_count_clone))?; - registry.register(Box::new(system_start_time_clone))?; - registry.register(Box::new(system_length_time_clone))?; - registry.register(Box::new(system_thread_avg_clone))?; - Ok(()) - }; - - Ok(( - Self { - system_length_hist, - system_length_count, - system_start_time, - system_length_time, - system_thread_avg, - }, - Box::new(f), - )) + Ok(Self { + system_length_hist, + system_length_count, + system_start_time, + system_length_time, + system_thread_avg, + }) } } impl PlayerMetrics { - pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> { + pub fn new(registry: &Registry) -> Result { let clients_connected = IntCounter::with_opts(Opts::new( "clients_connected", "shows the number of clients joined to the server", @@ -184,30 +160,20 @@ impl PlayerMetrics { &["reason"], )?; - let clients_connected_clone = clients_connected.clone(); - let players_connected_clone = players_connected.clone(); - let clients_disconnected_clone = clients_disconnected.clone(); + registry.register(Box::new(clients_connected.clone()))?; + registry.register(Box::new(players_connected.clone()))?; + registry.register(Box::new(clients_disconnected.clone()))?; - let f = |registry: &Registry| { - registry.register(Box::new(clients_connected_clone))?; - registry.register(Box::new(players_connected_clone))?; - registry.register(Box::new(clients_disconnected_clone))?; - Ok(()) - }; - - Ok(( - Self { - clients_connected, - players_connected, - clients_disconnected, - }, - Box::new(f), - )) + Ok(Self { + clients_connected, + players_connected, + clients_disconnected, + }) } } impl NetworkRequestMetrics { - pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> { + pub fn new(registry: &Registry) -> Result { let chunks_request_dropped = IntCounter::with_opts(Opts::new( "chunks_request_dropped", "number of all chunk request dropped, e.g because the player was to far away", @@ -221,30 +187,20 @@ impl NetworkRequestMetrics { "number of all chunks that were requested and needs to be generated", ))?; - let chunks_request_dropped_clone = chunks_request_dropped.clone(); - let chunks_served_from_memory_clone = chunks_served_from_memory.clone(); - let chunks_generation_triggered_clone = chunks_generation_triggered.clone(); + registry.register(Box::new(chunks_request_dropped.clone()))?; + registry.register(Box::new(chunks_served_from_memory.clone()))?; + registry.register(Box::new(chunks_generation_triggered.clone()))?; - let f = |registry: &Registry| { - registry.register(Box::new(chunks_request_dropped_clone))?; - registry.register(Box::new(chunks_served_from_memory_clone))?; - registry.register(Box::new(chunks_generation_triggered_clone))?; - Ok(()) - }; - - Ok(( - Self { - chunks_request_dropped, - chunks_served_from_memory, - chunks_generation_triggered, - }, - Box::new(f), - )) + Ok(Self { + chunks_request_dropped, + chunks_served_from_memory, + chunks_generation_triggered, + }) } } impl ChunkGenMetrics { - pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> { + pub fn new(registry: &Registry) -> Result { let chunks_requested = IntCounter::with_opts(Opts::new( "chunks_requested", "number of all chunks requested on the server", @@ -258,30 +214,20 @@ impl ChunkGenMetrics { "number of all canceled chunks on the server", ))?; - let chunks_requested_clone = chunks_requested.clone(); - let chunks_served_clone = chunks_served.clone(); - let chunks_canceled_clone = chunks_canceled.clone(); + registry.register(Box::new(chunks_requested.clone()))?; + registry.register(Box::new(chunks_served.clone()))?; + registry.register(Box::new(chunks_canceled.clone()))?; - let f = |registry: &Registry| { - registry.register(Box::new(chunks_requested_clone))?; - registry.register(Box::new(chunks_served_clone))?; - registry.register(Box::new(chunks_canceled_clone))?; - Ok(()) - }; - - Ok(( - Self { - chunks_requested, - chunks_served, - chunks_canceled, - }, - Box::new(f), - )) + Ok(Self { + chunks_requested, + chunks_served, + chunks_canceled, + }) } } impl TickMetrics { - pub fn new() -> Result<(Self, RegistryFn), Box> { + pub fn new(registry: &Registry) -> Result> { let chonks_count = IntGauge::with_opts(Opts::new( "chonks_count", "number of all chonks currently active on the server", @@ -322,42 +268,26 @@ impl TickMetrics { .expect("Time went backwards"); start_time.set(since_the_epoch.as_secs().try_into()?); - let chonks_count_clone = chonks_count.clone(); - let chunks_count_clone = chunks_count.clone(); - let chunk_groups_count_clone = chunk_groups_count.clone(); - let entity_count_clone = entity_count.clone(); - let build_info_clone = build_info.clone(); - let start_time_clone = start_time.clone(); - let time_of_day_clone = time_of_day.clone(); - let light_count_clone = light_count.clone(); - let tick_time_clone = tick_time.clone(); + registry.register(Box::new(chonks_count.clone()))?; + registry.register(Box::new(chunks_count.clone()))?; + registry.register(Box::new(chunk_groups_count.clone()))?; + registry.register(Box::new(entity_count.clone()))?; + registry.register(Box::new(build_info.clone()))?; + registry.register(Box::new(start_time.clone()))?; + registry.register(Box::new(time_of_day.clone()))?; + registry.register(Box::new(light_count.clone()))?; + registry.register(Box::new(tick_time.clone()))?; - let f = |registry: &Registry| { - registry.register(Box::new(chonks_count_clone))?; - registry.register(Box::new(chunks_count_clone))?; - registry.register(Box::new(chunk_groups_count_clone))?; - registry.register(Box::new(entity_count_clone))?; - registry.register(Box::new(build_info_clone))?; - registry.register(Box::new(start_time_clone))?; - registry.register(Box::new(time_of_day_clone))?; - registry.register(Box::new(light_count_clone))?; - registry.register(Box::new(tick_time_clone))?; - Ok(()) - }; - - Ok(( - Self { - chonks_count, - chunks_count, - chunk_groups_count, - entity_count, - tick_time, - build_info, - start_time, - time_of_day, - light_count, - }, - Box::new(f), - )) + Ok(Self { + chonks_count, + chunks_count, + chunk_groups_count, + entity_count, + tick_time, + build_info, + start_time, + time_of_day, + light_count, + }) } } From 989d13069280ad05d3bdbc50b6d4b40665fb8b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Mon, 8 Mar 2021 09:55:35 +0100 Subject: [PATCH 4/5] update state to system name. This will break grafana boards and thus needs an adjustment --- server/src/metrics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/metrics.rs b/server/src/metrics.rs index 596611cef8..2af96a5e46 100644 --- a/server/src/metrics.rs +++ b/server/src/metrics.rs @@ -93,16 +93,16 @@ impl EcsSystemMetrics { ]; let system_length_hist = HistogramVec::new( HistogramOpts::new( - "state_tick_time_hist", - "shows the number of clients joined to the server", + "system_length_hist", + "shows the detailed time in ns inside each ECS system as histogram", ) .buckets(bucket), &["system"], )?; let system_length_count = IntCounterVec::new( Opts::new( - "state_tick_time_count", - "shows the detailed time inside the `state_tick` for each system", + "system_length_count", + "shows the detailed time in ns inside each ECS system", ), &["system"], )?; From f353f14703483d6603a571e696da5458d38dbbc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Mon, 8 Mar 2021 12:13:59 +0100 Subject: [PATCH 5/5] change Name from VSystem to System --- common/src/lib.rs | 2 +- common/src/metrics.rs | 2 +- common/src/{vsystem.rs => system.rs} | 34 +++++++++++++------------- common/sys/src/aura.rs | 6 ++--- common/sys/src/beam.rs | 6 ++--- common/sys/src/buff.rs | 6 ++--- common/sys/src/character_behavior.rs | 6 ++--- common/sys/src/controller.rs | 6 ++--- common/sys/src/lib.rs | 2 +- common/sys/src/melee.rs | 6 ++--- common/sys/src/mount.rs | 6 ++--- common/sys/src/phys.rs | 6 ++--- common/sys/src/projectile.rs | 9 +++---- common/sys/src/shockwave.rs | 6 ++--- common/sys/src/stats.rs | 6 ++--- server/src/lib.rs | 2 +- server/src/rtsim/load_chunks.rs | 6 ++--- server/src/rtsim/mod.rs | 2 +- server/src/rtsim/tick.rs | 6 ++--- server/src/rtsim/unload_chunks.rs | 6 ++--- server/src/sys/agent.rs | 6 ++--- server/src/sys/entity_sync.rs | 6 ++--- server/src/sys/invite_timeout.rs | 6 ++--- server/src/sys/metrics.rs | 8 +++--- server/src/sys/mod.rs | 2 +- server/src/sys/msg/character_screen.rs | 6 ++--- server/src/sys/msg/general.rs | 6 ++--- server/src/sys/msg/in_game.rs | 6 ++--- server/src/sys/msg/ping.rs | 6 ++--- server/src/sys/object.rs | 6 ++--- server/src/sys/persistence.rs | 6 ++--- server/src/sys/sentinel.rs | 6 ++--- server/src/sys/subscription.rs | 6 ++--- server/src/sys/terrain.rs | 6 ++--- server/src/sys/terrain_sync.rs | 6 ++--- server/src/sys/waypoint.rs | 6 ++--- voxygen/src/ecs/sys.rs | 2 +- voxygen/src/ecs/sys/floater.rs | 6 ++--- voxygen/src/ecs/sys/interpolation.rs | 6 ++--- 39 files changed, 118 insertions(+), 121 deletions(-) rename common/src/{vsystem.rs => system.rs} (95%) diff --git a/common/src/lib.rs b/common/src/lib.rs index c3e8501488..7bbad0249a 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -61,6 +61,7 @@ pub mod spiral; #[cfg(not(target_arch = "wasm32"))] pub mod states; #[cfg(not(target_arch = "wasm32"))] pub mod store; +pub mod system; #[cfg(not(target_arch = "wasm32"))] pub mod terrain; #[cfg(not(target_arch = "wasm32"))] pub mod time; @@ -71,7 +72,6 @@ pub mod uid; #[cfg(not(target_arch = "wasm32"))] pub mod vol; #[cfg(not(target_arch = "wasm32"))] pub mod volumes; -pub mod vsystem; pub use combat::DamageSource; #[cfg(not(target_arch = "wasm32"))] diff --git a/common/src/metrics.rs b/common/src/metrics.rs index d1f9a81997..c919786e1f 100644 --- a/common/src/metrics.rs +++ b/common/src/metrics.rs @@ -1,4 +1,4 @@ -use crate::vsystem::CpuTimeline; +use crate::system::CpuTimeline; use std::{collections::HashMap, sync::Mutex}; #[derive(Default)] diff --git a/common/src/vsystem.rs b/common/src/system.rs similarity index 95% rename from common/src/vsystem.rs rename to common/src/system.rs index b1af1ee844..36eb5697da 100644 --- a/common/src/vsystem.rs +++ b/common/src/system.rs @@ -1,5 +1,5 @@ use crate::metrics::SysMetrics; -use specs::{ReadExpect, RunNow, System}; +use specs::{ReadExpect, RunNow}; use std::{collections::HashMap, time::Instant}; /// measuring the level of threads a unit of code ran on. Use Rayon when it ran @@ -32,7 +32,7 @@ pub enum Origin { #[derive(Default, Debug, Clone)] pub struct CpuTimeline { - /// + /// measurements for a System /// - The first entry will always be ParMode::Single, as when the /// System::run is executed, we run /// single threaded until we start a Rayon::ParIter or similar @@ -71,7 +71,7 @@ impl CpuTimeline { } /// Start a new measurement. par will be covering the parallelisation AFTER - /// this statement, till the next / end of the VSystem. + /// this statement, till the next / end of the System. pub fn measure(&mut self, par: ParMode) { self.measures.push((Instant::now(), par)); } fn end(&mut self) { self.measures.push((Instant::now(), ParMode::None)); } @@ -191,17 +191,17 @@ pub fn gen_stats( /// /// ``` /// use specs::Read; -/// pub use veloren_common::vsystem::{Origin, ParMode, Phase, VJob, VSystem}; +/// pub use veloren_common::system::{Job, Origin, ParMode, Phase, System}; /// # use std::time::Duration; /// pub struct Sys; -/// impl<'a> VSystem<'a> for Sys { +/// impl<'a> System<'a> for Sys { /// type SystemData = (Read<'a, ()>, Read<'a, ()>); /// /// const NAME: &'static str = "example"; /// const ORIGIN: Origin = Origin::Frontend("voxygen"); /// const PHASE: Phase = Phase::Create; /// -/// fn run(job: &mut VJob, (_read, _read2): Self::SystemData) { +/// fn run(job: &mut Job, (_read, _read2): Self::SystemData) { /// std::thread::sleep(Duration::from_millis(100)); /// job.cpu_stats.measure(ParMode::Rayon); /// std::thread::sleep(Duration::from_millis(500)); @@ -210,33 +210,33 @@ pub fn gen_stats( /// } /// } /// ``` -pub trait VSystem<'a> { +pub trait System<'a> { const NAME: &'static str; const PHASE: Phase; const ORIGIN: Origin; type SystemData: specs::SystemData<'a>; - fn run(job: &mut VJob, data: Self::SystemData); + fn run(job: &mut Job, data: Self::SystemData); fn sys_name() -> String { format!("{}_sys", Self::NAME) } } pub fn dispatch<'a, 'b, T>(builder: &mut specs::DispatcherBuilder<'a, 'b>, dep: &[&str]) where - T: for<'c> VSystem<'c> + Send + 'a + Default, + T: for<'c> System<'c> + Send + 'a + Default, { - builder.add(VJob::::default(), &T::sys_name(), dep); + builder.add(Job::::default(), &T::sys_name(), dep); } pub fn run_now<'a, 'b, T>(world: &'a specs::World) where - T: for<'c> VSystem<'c> + Send + 'a + Default, + T: for<'c> System<'c> + Send + 'a + Default, { - VJob::::default().run_now(world); + Job::::default().run_now(world); } /// This Struct will wrap the System in order to avoid the can only impl trait /// for local defined structs error It also contains the cpu measurements -pub struct VJob +pub struct Job where T: ?Sized, { @@ -244,9 +244,9 @@ where pub cpu_stats: CpuTimeline, } -impl<'a, T> System<'a> for VJob +impl<'a, T> specs::System<'a> for Job where - T: VSystem<'a>, + T: System<'a>, { type SystemData = (T::SystemData, ReadExpect<'a, SysMetrics>); @@ -263,9 +263,9 @@ where } } -impl<'a, T> Default for VJob +impl<'a, T> Default for Job where - T: VSystem<'a> + Default, + T: System<'a> + Default, { fn default() -> Self { Self { diff --git a/common/sys/src/aura.rs b/common/sys/src/aura.rs index e1bd0628b6..90829a39e0 100644 --- a/common/sys/src/aura.rs +++ b/common/sys/src/aura.rs @@ -7,8 +7,8 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::DeltaTime, + system::{Job, Origin, Phase, System}, uid::UidAllocator, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, @@ -30,7 +30,7 @@ pub struct ReadData<'a> { #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Auras>, @@ -41,7 +41,7 @@ impl<'a> VSystem<'a> for Sys { const ORIGIN: Origin = Origin::Common; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (read_data, mut auras, mut buffs): Self::SystemData) { + fn run(_job: &mut Job, (read_data, mut auras, mut buffs): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); let dt = read_data.dt.0; diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index 99564ecc84..60ebd77d07 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -6,8 +6,8 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, + system::{Job, Origin, Phase, System}, uid::{Uid, UidAllocator}, - vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ @@ -40,7 +40,7 @@ pub struct ReadData<'a> { /// This system is responsible for handling beams that heal or do damage #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, BeamSegment>, @@ -51,7 +51,7 @@ impl<'a> VSystem<'a> for Sys { const ORIGIN: Origin = Origin::Common; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (read_data, mut beam_segments, mut beams): Self::SystemData) { + fn run(_job: &mut Job, (read_data, mut beam_segments, mut beams): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); let time = read_data.time.0; diff --git a/common/sys/src/buff.rs b/common/sys/src/buff.rs index 3f2d24e0aa..9453e64b4b 100644 --- a/common/sys/src/buff.rs +++ b/common/sys/src/buff.rs @@ -5,7 +5,7 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::DeltaTime, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, Damage, DamageSource, }; use specs::{ @@ -23,7 +23,7 @@ pub struct ReadData<'a> { #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Health>, @@ -37,7 +37,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (read_data, mut healths, mut energies, mut buffs, mut stats): Self::SystemData, ) { let mut server_emitter = read_data.server_bus.emitter(); diff --git a/common/sys/src/character_behavior.rs b/common/sys/src/character_behavior.rs index 1751d2d73f..8783f29955 100644 --- a/common/sys/src/character_behavior.rs +++ b/common/sys/src/character_behavior.rs @@ -18,8 +18,8 @@ use common::{ self, behavior::{CharacterBehavior, JoinData, JoinStruct}, }, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use std::time::Duration; @@ -73,7 +73,7 @@ pub struct ReadData<'a> { #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, @@ -93,7 +93,7 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::while_let_on_iterator)] // TODO: Pending review in #587 fn run( - _job: &mut VJob, + _job: &mut Job, ( read_data, mut character_states, diff --git a/common/sys/src/controller.rs b/common/sys/src/controller.rs index e16fb40c14..40c0a07ce9 100644 --- a/common/sys/src/controller.rs +++ b/common/sys/src/controller.rs @@ -1,8 +1,8 @@ use common::{ comp::{BuffChange, ControlEvent, Controller}, event::{EventBus, ServerEvent}, + system::{Job, Origin, Phase, System}, uid::UidAllocator, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::{Marker, MarkerAllocator}, @@ -21,14 +21,14 @@ pub struct ReadData<'a> { #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = (ReadData<'a>, WriteStorage<'a, Controller>); const NAME: &'static str = "controller"; const ORIGIN: Origin = Origin::Common; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (read_data, mut controllers): Self::SystemData) { + fn run(_job: &mut Job, (read_data, mut controllers): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); for (entity, controller) in (&read_data.entities, &mut controllers).join() { diff --git a/common/sys/src/lib.rs b/common/sys/src/lib.rs index 72da8cf129..c0dc0e99bf 100644 --- a/common/sys/src/lib.rs +++ b/common/sys/src/lib.rs @@ -15,7 +15,7 @@ pub mod state; mod stats; // External -use common::vsystem::{dispatch, VSystem}; +use common::system::{dispatch, System}; use specs::DispatcherBuilder; pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index 5a84b3172a..7bf88d813a 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -2,9 +2,9 @@ use common::{ combat::{AttackerInfo, TargetInfo}, comp::{Body, CharacterState, Energy, Group, Health, Inventory, Melee, Ori, Pos, Scale, Stats}, event::{EventBus, ServerEvent}, + system::{Job, Origin, Phase, System}, uid::Uid, util::Dir, - vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ @@ -34,14 +34,14 @@ pub struct ReadData<'a> { #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = (ReadData<'a>, WriteStorage<'a, Melee>); const NAME: &'static str = "melee"; const ORIGIN: Origin = Origin::Common; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (read_data, mut melee_attacks): Self::SystemData) { + fn run(_job: &mut Job, (read_data, mut melee_attacks): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); // Attacks for (attacker, uid, pos, ori, melee_attack, body) in ( diff --git a/common/sys/src/mount.rs b/common/sys/src/mount.rs index 5b68cbe758..68f1bedb9c 100644 --- a/common/sys/src/mount.rs +++ b/common/sys/src/mount.rs @@ -1,7 +1,7 @@ use common::{ comp::{Controller, MountState, Mounting, Ori, Pos, Vel}, + system::{Job, Origin, Phase, System}, uid::UidAllocator, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{ saveload::{Marker, MarkerAllocator}, @@ -12,7 +12,7 @@ use vek::*; /// This system is responsible for controlling mounts #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, UidAllocator>, @@ -30,7 +30,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( uid_allocator, entities, diff --git a/common/sys/src/phys.rs b/common/sys/src/phys.rs index e246fcabdb..c8277ec0db 100644 --- a/common/sys/src/phys.rs +++ b/common/sys/src/phys.rs @@ -8,10 +8,10 @@ use common::{ metrics::PhysicsMetrics, resources::DeltaTime, span, + system::{Job, Origin, ParMode, Phase, System}, terrain::{Block, TerrainGrid}, uid::Uid, vol::ReadVol, - vsystem::{Origin, ParMode, Phase, VJob, VSystem}, }; use rayon::iter::ParallelIterator; use specs::{Entities, Join, ParJoin, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage}; @@ -63,7 +63,7 @@ fn calc_z_limit( #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -96,7 +96,7 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587 fn run( - job: &mut VJob, + job: &mut Job, ( entities, uids, diff --git a/common/sys/src/projectile.rs b/common/sys/src/projectile.rs index 27bfb73da6..b09c28d10d 100644 --- a/common/sys/src/projectile.rs +++ b/common/sys/src/projectile.rs @@ -6,9 +6,9 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::DeltaTime, + system::{Job, Origin, Phase, System}, uid::UidAllocator, util::Dir, - vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ @@ -35,7 +35,7 @@ pub struct ReadData<'a> { /// This system is responsible for handling projectile effect triggers #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Ori>, @@ -46,10 +46,7 @@ impl<'a> VSystem<'a> for Sys { const ORIGIN: Origin = Origin::Common; const PHASE: Phase = Phase::Create; - fn run( - _job: &mut VJob, - (read_data, mut orientations, mut projectiles): Self::SystemData, - ) { + fn run(_job: &mut Job, (read_data, mut orientations, mut projectiles): Self::SystemData) { let mut server_emitter = read_data.server_bus.emitter(); // Attacks diff --git a/common/sys/src/shockwave.rs b/common/sys/src/shockwave.rs index 5699b1b22f..20b084e3df 100644 --- a/common/sys/src/shockwave.rs +++ b/common/sys/src/shockwave.rs @@ -6,9 +6,9 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, + system::{Job, Origin, Phase, System}, uid::{Uid, UidAllocator}, util::Dir, - vsystem::{Origin, Phase, VJob, VSystem}, GroupTarget, }; use specs::{ @@ -42,7 +42,7 @@ pub struct ReadData<'a> { /// attacking #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = ( ReadData<'a>, WriteStorage<'a, Shockwave>, @@ -54,7 +54,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (read_data, mut shockwaves, mut shockwave_hit_lists): Self::SystemData, ) { let mut server_emitter = read_data.server_bus.emitter(); diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index 955a642735..caa403d9a9 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -7,8 +7,8 @@ use common::{ event::{EventBus, ServerEvent}, outcome::Outcome, resources::{DeltaTime, Time}, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use hashbrown::HashSet; use specs::{ @@ -35,7 +35,7 @@ pub struct ReadData<'a> { /// This system kills players, levels them up, and regenerates energy. #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, @@ -52,7 +52,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( read_data, mut stats, diff --git a/server/src/lib.rs b/server/src/lib.rs index 8b83cf7e88..4729a738ba 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -64,9 +64,9 @@ use common::{ recipe::default_recipe_book, resources::TimeOfDay, rtsim::RtSimEntity, + system::run_now, terrain::TerrainChunkSize, vol::{ReadVol, RectVolSize}, - vsystem::run_now, }; use common_net::{ msg::{ diff --git a/server/src/rtsim/load_chunks.rs b/server/src/rtsim/load_chunks.rs index 1dde223a96..37ecb29dae 100644 --- a/server/src/rtsim/load_chunks.rs +++ b/server/src/rtsim/load_chunks.rs @@ -1,13 +1,13 @@ use super::*; use common::{ event::{EventBus, ServerEvent}, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, }; use specs::{Read, WriteExpect}; #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = (Read<'a, EventBus>, WriteExpect<'a, RtSim>); @@ -15,7 +15,7 @@ impl<'a> VSystem<'a> for Sys { const ORIGIN: Origin = Origin::Server; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (_server_event_bus, mut rtsim): Self::SystemData) { + fn run(_job: &mut Job, (_server_event_bus, mut rtsim): Self::SystemData) { for _chunk in std::mem::take(&mut rtsim.chunks.chunks_to_load) { // TODO } diff --git a/server/src/rtsim/mod.rs b/server/src/rtsim/mod.rs index 6bdeb93f8f..dca14151c3 100644 --- a/server/src/rtsim/mod.rs +++ b/server/src/rtsim/mod.rs @@ -10,9 +10,9 @@ use self::{chunks::Chunks, entity::Entity}; use common::{ comp, rtsim::{RtSimController, RtSimEntity, RtSimId}, + system::{dispatch, System}, terrain::TerrainChunk, vol::RectRasterableVol, - vsystem::{dispatch, VSystem}, }; use common_sys::state::State; use rand::prelude::*; diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index afb8847e9a..312c403661 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -6,8 +6,8 @@ use common::{ comp::inventory::loadout_builder::LoadoutBuilder, event::{EventBus, ServerEvent}, resources::DeltaTime, + system::{Job, Origin, Phase, System}, terrain::TerrainGrid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage}; use std::sync::Arc; @@ -16,7 +16,7 @@ const ENTITY_TICK_PERIOD: u64 = 30; #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, DeltaTime>, @@ -35,7 +35,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( dt, server_event_bus, diff --git a/server/src/rtsim/unload_chunks.rs b/server/src/rtsim/unload_chunks.rs index f05800fb87..eb9c85f79f 100644 --- a/server/src/rtsim/unload_chunks.rs +++ b/server/src/rtsim/unload_chunks.rs @@ -2,14 +2,14 @@ use super::*; use common::{ comp::Pos, event::{EventBus, ServerEvent}, + system::{Job, Origin, Phase, System}, terrain::TerrainGrid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{Entities, Read, ReadExpect, ReadStorage, WriteExpect}; #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Read<'a, EventBus>, @@ -25,7 +25,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( _server_event_bus, mut rtsim, diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index d67d9a448e..d3dcfb6364 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -17,12 +17,12 @@ use common::{ event::{Emitter, EventBus, ServerEvent}, path::TraversalConfig, resources::{DeltaTime, TimeOfDay}, + system::{Job, Origin, Phase, System}, terrain::{Block, TerrainGrid}, time::DayPeriod, uid::{Uid, UidAllocator}, util::Dir, vol::ReadVol, - vsystem::{Origin, Phase, VJob, VSystem}, }; use rand::{thread_rng, Rng}; use rayon::iter::ParallelIterator; @@ -98,7 +98,7 @@ const AVG_FOLLOW_DIST: f32 = 6.0; /// This system will allow NPCs to modify their controller #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, @@ -113,7 +113,7 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 fn run( - _job: &mut VJob, + _job: &mut Job, (read_data, event_bus, mut agents, mut controllers): Self::SystemData, ) { ( diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 43903b84ba..1684770436 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -9,10 +9,10 @@ use common::{ outcome::Outcome, region::{Event as RegionEvent, RegionMap}, resources::TimeOfDay, + system::{Job, Origin, Phase, System}, terrain::TerrainChunkSize, uid::Uid, vol::RectVolSize, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::{msg::ServerGeneral, sync::CompSyncPackage}; use specs::{ @@ -23,7 +23,7 @@ use vek::*; /// This system will send physics updates to the client #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -54,7 +54,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, tick, diff --git a/server/src/sys/invite_timeout.rs b/server/src/sys/invite_timeout.rs index ed155d3bf3..d08f9e848e 100644 --- a/server/src/sys/invite_timeout.rs +++ b/server/src/sys/invite_timeout.rs @@ -1,8 +1,8 @@ use crate::client::Client; use common::{ comp::invite::{Invite, PendingInvites}, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{InviteAnswer, ServerGeneral}; use specs::{Entities, Join, ReadStorage, WriteStorage}; @@ -10,7 +10,7 @@ use specs::{Entities, Join, ReadStorage, WriteStorage}; /// This system removes timed out invites #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -25,7 +25,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (entities, mut invites, mut pending_invites, clients, uids): Self::SystemData, ) { let now = std::time::Instant::now(); diff --git a/server/src/sys/metrics.rs b/server/src/sys/metrics.rs index 60d7c2d5d0..b991622538 100644 --- a/server/src/sys/metrics.rs +++ b/server/src/sys/metrics.rs @@ -5,8 +5,8 @@ use crate::{ use common::{ metrics::SysMetrics, resources::TimeOfDay, + system::{Job, Origin, Phase, System}, terrain::TerrainGrid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{Entities, Join, Read, ReadExpect}; use std::time::Instant; @@ -14,7 +14,7 @@ use std::time::Instant; /// This system exports metrics #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Option>, @@ -34,7 +34,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Apply; fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, tick, @@ -56,7 +56,7 @@ impl<'a> VSystem<'a> for Sys { //this system hasn't run yet state.remove(Self::NAME); - for (name, stat) in common::vsystem::gen_stats(&state, tick_start.0, 8, 8) { + for (name, stat) in common::system::gen_stats(&state, tick_start.0, 8, 8) { export_ecs .system_start_time .with_label_values(&[&name]) diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 594b8c9be3..0995c82859 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -11,7 +11,7 @@ pub mod terrain; pub mod terrain_sync; pub mod waypoint; -use common::vsystem::{dispatch, run_now}; +use common::system::{dispatch, run_now}; use specs::DispatcherBuilder; use std::{ marker::PhantomData, diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index 1ef07dfc19..6bd591ec74 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -5,8 +5,8 @@ use crate::{ use common::{ comp::{ChatType, Player, UnresolvedChatMsg}, event::{EventBus, ServerEvent}, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ClientGeneral, ServerGeneral}; use specs::{Entities, Join, Read, ReadExpect, ReadStorage}; @@ -122,7 +122,7 @@ impl Sys { /// This system will handle new messages from clients #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -141,7 +141,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, server_event_bus, diff --git a/server/src/sys/msg/general.rs b/server/src/sys/msg/general.rs index 9da374a9d5..7928218efd 100644 --- a/server/src/sys/msg/general.rs +++ b/server/src/sys/msg/general.rs @@ -3,8 +3,8 @@ use common::{ comp::{ChatMode, Player, UnresolvedChatMsg}, event::{EventBus, ServerEvent}, resources::Time, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ validate_chat_msg, ChatMsgValidationError, ClientGeneral, MAX_BYTES_CHAT_MSG, @@ -66,7 +66,7 @@ impl Sys { /// This system will handle new messages from clients #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -84,7 +84,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, server_event_bus, diff --git a/server/src/sys/msg/in_game.rs b/server/src/sys/msg/in_game.rs index e35359baa1..af11dc1b20 100644 --- a/server/src/sys/msg/in_game.rs +++ b/server/src/sys/msg/in_game.rs @@ -2,9 +2,9 @@ use crate::{client::Client, metrics::NetworkRequestMetrics, presence::Presence, use common::{ comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, Stats, Vel}, event::{EventBus, ServerEvent}, + system::{Job, Origin, Phase, System}, terrain::{TerrainChunkSize, TerrainGrid}, vol::{ReadVol, RectVolSize}, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{ClientGeneral, PresenceKind, ServerGeneral}; use common_sys::state::BlockChange; @@ -166,7 +166,7 @@ impl Sys { /// This system will handle new messages from clients #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -192,7 +192,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, server_event_bus, diff --git a/server/src/sys/msg/ping.rs b/server/src/sys/msg/ping.rs index 90251c34fb..2ec8b4e907 100644 --- a/server/src/sys/msg/ping.rs +++ b/server/src/sys/msg/ping.rs @@ -2,7 +2,7 @@ use crate::{client::Client, metrics::PlayerMetrics, Settings}; use common::{ event::{EventBus, ServerEvent}, resources::Time, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, }; use common_net::msg::PingMsg; use specs::{Entities, Join, Read, ReadExpect, ReadStorage}; @@ -22,7 +22,7 @@ impl Sys { /// This system will handle new messages from clients #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -38,7 +38,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (entities, server_event_bus, time, player_metrics, clients, settings): Self::SystemData, ) { let mut server_emitter = server_event_bus.emitter(); diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index a5aee2f43f..b24cc0224b 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -3,7 +3,7 @@ use common::{ effect::Effect, event::{EventBus, ServerEvent}, resources::DeltaTime, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, Damage, DamageSource, Explosion, RadiusEffect, }; use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; @@ -11,7 +11,7 @@ use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; /// This system is responsible for handling misc object behaviours #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -28,7 +28,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (entities, _dt, server_bus, positions, velocities, physics_states, mut objects): Self::SystemData, ) { let mut server_emitter = server_bus.emitter(); diff --git a/server/src/sys/persistence.rs b/server/src/sys/persistence.rs index 9feaed9cec..12b2c07695 100644 --- a/server/src/sys/persistence.rs +++ b/server/src/sys/persistence.rs @@ -1,7 +1,7 @@ use crate::{persistence::character_updater, presence::Presence, sys::SysScheduler}; use common::{ comp::{Inventory, Stats, Waypoint}, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, }; use common_net::msg::PresenceKind; use specs::{Join, ReadExpect, ReadStorage, Write}; @@ -9,7 +9,7 @@ use specs::{Join, ReadExpect, ReadStorage, Write}; #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadStorage<'a, Presence>, @@ -25,7 +25,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( presences, player_stats, diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index fab165a31e..394f966fbb 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -4,8 +4,8 @@ use common::{ Gravity, Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori, Player, Poise, Pos, Scale, Shockwave, Stats, Sticky, Vel, }, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::{ msg::EcsCompPacket, @@ -23,14 +23,14 @@ use vek::*; /// modification #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { type SystemData = (TrackedComps<'a>, WriteTrackers<'a>); const NAME: &'static str = "sentinel"; const ORIGIN: Origin = Origin::Server; const PHASE: Phase = Phase::Create; - fn run(_job: &mut VJob, (comps, mut trackers): Self::SystemData) { + fn run(_job: &mut Job, (comps, mut trackers): Self::SystemData) { record_changes(&comps, &mut trackers); } } diff --git a/server/src/sys/subscription.rs b/server/src/sys/subscription.rs index 8dfda871c0..51a242e1d8 100644 --- a/server/src/sys/subscription.rs +++ b/server/src/sys/subscription.rs @@ -6,10 +6,10 @@ use crate::{ use common::{ comp::{Ori, Pos, Vel}, region::{region_in_vd, regions_in_vd, Event as RegionEvent, RegionMap}, + system::{Job, Origin, Phase, System}, terrain::TerrainChunkSize, uid::Uid, vol::RectVolSize, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::ServerGeneral; use specs::{ @@ -21,7 +21,7 @@ use vek::*; /// This system will update region subscriptions based on client positions #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -43,7 +43,7 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587 fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, region_map, diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index f24495dda2..8f21a42324 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -6,8 +6,8 @@ use common::{ event::{EventBus, ServerEvent}, generation::get_npc_name, npc::NPC_NAMES, + system::{Job, Origin, Phase, System}, terrain::TerrainGrid, - vsystem::{Origin, Phase, VJob, VSystem}, LoadoutBuilder, SkillSetBuilder, }; use common_net::msg::ServerGeneral; @@ -24,7 +24,7 @@ use vek::*; /// 4. Removes chunks outside the range of players #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Read<'a, EventBus>, @@ -43,7 +43,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( server_event_bus, tick, diff --git a/server/src/sys/terrain_sync.rs b/server/src/sys/terrain_sync.rs index 874186847c..070bfa8880 100644 --- a/server/src/sys/terrain_sync.rs +++ b/server/src/sys/terrain_sync.rs @@ -1,8 +1,8 @@ use crate::{client::Client, presence::Presence}; use common::{ comp::Pos, + system::{Job, Origin, Phase, System}, terrain::TerrainGrid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::ServerGeneral; use common_sys::state::TerrainChanges; @@ -12,7 +12,7 @@ use specs::{Join, Read, ReadExpect, ReadStorage}; /// chunks #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadExpect<'a, TerrainGrid>, @@ -27,7 +27,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (terrain, terrain_changes, positions, presences, clients): Self::SystemData, ) { // Sync changed chunks diff --git a/server/src/sys/waypoint.rs b/server/src/sys/waypoint.rs index 05945179f2..7107fc79c5 100644 --- a/server/src/sys/waypoint.rs +++ b/server/src/sys/waypoint.rs @@ -2,7 +2,7 @@ use crate::client::Client; use common::{ comp::{Player, Pos, Waypoint, WaypointArea}, resources::Time, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, }; use common_net::msg::{Notification, ServerGeneral}; use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; @@ -14,7 +14,7 @@ const NOTIFY_TIME: f64 = 10.0; /// TODO: Make this faster by only considering local waypoints #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -31,7 +31,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, ( entities, positions, diff --git a/voxygen/src/ecs/sys.rs b/voxygen/src/ecs/sys.rs index 7405e0de8f..a9810a35b0 100644 --- a/voxygen/src/ecs/sys.rs +++ b/voxygen/src/ecs/sys.rs @@ -1,7 +1,7 @@ pub mod floater; mod interpolation; -use common::vsystem::{dispatch, VSystem}; +use common::system::{dispatch, System}; use specs::DispatcherBuilder; pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { diff --git a/voxygen/src/ecs/sys/floater.rs b/voxygen/src/ecs/sys/floater.rs index 1fc849de7f..164ca568c4 100644 --- a/voxygen/src/ecs/sys/floater.rs +++ b/voxygen/src/ecs/sys/floater.rs @@ -5,8 +5,8 @@ use crate::ecs::{ use common::{ comp::{Health, HealthSource, Pos}, resources::DeltaTime, + system::{Job, Origin, Phase, System}, uid::Uid, - vsystem::{Origin, Phase, VJob, VSystem}, }; use specs::{Entities, Join, Read, ReadExpect, ReadStorage, WriteStorage}; @@ -17,7 +17,7 @@ pub const HP_ACCUMULATETIME: f32 = 1.0; #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -35,7 +35,7 @@ impl<'a> VSystem<'a> for Sys { #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587 fn run( - _job: &mut VJob, + _job: &mut Job, (entities, my_entity, dt, uids, pos, healths, mut hp_floater_lists): Self::SystemData, ) { // Add hp floater lists to all entities with health and a position diff --git a/voxygen/src/ecs/sys/interpolation.rs b/voxygen/src/ecs/sys/interpolation.rs index 34954612b4..2b96957150 100644 --- a/voxygen/src/ecs/sys/interpolation.rs +++ b/voxygen/src/ecs/sys/interpolation.rs @@ -2,7 +2,7 @@ use crate::ecs::comp::Interpolated; use common::{ comp::{object, Body, Ori, Pos, Vel}, resources::DeltaTime, - vsystem::{Origin, Phase, VJob, VSystem}, + system::{Job, Origin, Phase, System}, }; use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; use tracing::warn; @@ -11,7 +11,7 @@ use vek::*; /// This system will allow NPCs to modify their controller #[derive(Default)] pub struct Sys; -impl<'a> VSystem<'a> for Sys { +impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, @@ -28,7 +28,7 @@ impl<'a> VSystem<'a> for Sys { const PHASE: Phase = Phase::Create; fn run( - _job: &mut VJob, + _job: &mut Job, (entities, dt, positions, orientations, velocities, bodies, mut interpolated): Self::SystemData, ) { // Update interpolated positions and orientations