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
This commit is contained in:
Marcel Märtens 2021-03-08 09:36:53 +01:00
parent c515fece28
commit 6b88545481
27 changed files with 241 additions and 566 deletions

View File

@ -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<HashMap<String, CpuTimeline>>,
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)]

View File

@ -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<LocalEvent>>,
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,
);
}
}

View File

@ -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<ServerEvent>>,
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<Self>, (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,
);
}
}

View File

@ -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<ServerEvent>>,
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<Self>, (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,
);
}
}

View File

@ -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<Self>,
(
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,
);
}
}

View File

@ -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<ServerEvent>>,
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,
);
}
}

View File

@ -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<ServerEvent>>,
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<Self>,
(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,
);
}
}

View File

@ -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<ServerEvent>>,
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,
);
}
}

View File

@ -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<f32>);
#[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<World>,
@ -129,9 +133,6 @@ pub struct Server {
runtime: Arc<Runtime>,
metrics_shutdown: Arc<Notify>,
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(&registry).expect("failed to register chunk gen metrics");
registry_network(&registry).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<Vec<Event>, Error> {
self.state.ecs().write_resource::<Tick>().0 += 1;
self.state.ecs().write_resource::<TickStart>().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::<sys::metrics::Sys>(&self.state.ecs());
{
let lock = self
.state
.ecs()
.read_resource::<common::metrics::SysMetrics>();
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::<metrics::TickMetrics>();
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::<sys::AgentTimer>().nanos as i64;
let entity_sync_nanos = self
.state
.ecs()
.read_resource::<sys::EntitySyncTimer>()
.nanos as i64;
let message_nanos = {
let state = self.state.ecs();
(state.read_resource::<sys::GeneralMsgTimer>().nanos
+ state.read_resource::<sys::PingMsgTimer>().nanos
+ state.read_resource::<sys::CharacterScreenMsgTimer>().nanos
+ state.read_resource::<sys::InGameMsgTimer>().nanos) as i64
};
let sentinel_nanos = self.state.ecs().read_resource::<sys::SentinelTimer>().nanos as i64;
let subscription_nanos = self
.state
.ecs()
.read_resource::<sys::SubscriptionTimer>()
.nanos as i64;
let terrain_sync_nanos = self
.state
.ecs()
.read_resource::<sys::TerrainSyncTimer>()
.nanos as i64;
let terrain_nanos = self.state.ecs().read_resource::<sys::TerrainTimer>().nanos as i64;
let waypoint_nanos = self.state.ecs().read_resource::<sys::WaypointTimer>().nanos as i64;
let invite_timeout_nanos = self
.state
.ecs()
.read_resource::<sys::InviteTimeoutTimer>()
.nanos as i64;
let stats_persistence_nanos = self
.state
.ecs()
.read_resource::<sys::PersistenceTimer>()
.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::<common::metrics::SysMetrics>();
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::<common::metrics::PhysicsMetrics>();
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::<TimeOfDay>().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)

View File

@ -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<AtomicU64>,
}
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 }
}

View File

@ -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<Self>>,
Write<'a, EventBus<ServerEvent>>,
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<Self>,
(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();
}
}

View File

@ -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<Self>>,
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();
}
}

View File

@ -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<Self>>,
);
const NAME: &'static str = "invite_timeout";
@ -28,12 +26,9 @@ impl<'a> VSystem<'a> for Sys {
fn run(
_job: &mut VJob<Self>,
(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();
}
}

128
server/src/sys/metrics.rs Normal file
View File

@ -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<Entities<'a>>,
ReadExpect<'a, Tick>,
ReadExpect<'a, TimeOfDay>,
ReadExpect<'a, TickStart>,
Option<Read<'a, TerrainGrid>>,
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<Self>,
(
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);
}
}

View File

@ -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<entity_sync::Sys>;
pub type GeneralMsgTimer = SysTimer<msg::general::Sys>;
pub type PingMsgTimer = SysTimer<msg::ping::Sys>;
pub type CharacterScreenMsgTimer = SysTimer<msg::character_screen::Sys>;
pub type InGameMsgTimer = SysTimer<msg::in_game::Sys>;
pub type SentinelTimer = SysTimer<sentinel::Sys>;
pub type SubscriptionTimer = SysTimer<subscription::Sys>;
pub type TerrainTimer = SysTimer<terrain::Sys>;
pub type TerrainSyncTimer = SysTimer<terrain_sync::Sys>;
pub type WaypointTimer = SysTimer<waypoint::Sys>;
pub type InviteTimeoutTimer = SysTimer<invite_timeout::Sys>;
pub type PersistenceTimer = SysTimer<persistence::Sys>;
pub type PersistenceScheduler = SysScheduler<persistence::Sys>;
pub type AgentTimer = SysTimer<agent::Sys>;
pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) {
dispatch::<terrain::Sys>(dispatch_builder, &[]);
@ -87,38 +75,3 @@ impl<S> Default for SysScheduler<S> {
}
}
}
/// Used to keep track of how much time each system takes
pub struct SysTimer<S> {
pub nanos: u64,
start: Option<Instant>,
_phantom: PhantomData<S>,
}
impl<S> SysTimer<S> {
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<S> Default for SysTimer<S> {
fn default() -> Self {
Self {
nanos: 0,
start: None,
_phantom: PhantomData,
}
}
}

View File

@ -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<ServerEvent>>,
ReadExpect<'a, CharacterLoader>,
Write<'a, SysTimer<Self>>,
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()
}
}

View File

@ -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<ServerEvent>>,
Read<'a, Time>,
ReadExpect<'a, PlayerMetrics>,
Write<'a, SysTimer<Self>>,
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()
}
}

View File

@ -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<ServerEvent>>,
ReadExpect<'a, TerrainGrid>,
ReadExpect<'a, NetworkRequestMetrics>,
Write<'a, SysTimer<Self>>,
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()
}
}

View File

@ -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<ServerEvent>>,
Read<'a, Time>,
ReadExpect<'a, PlayerMetrics>,
Write<'a, SysTimer<Self>>,
ReadStorage<'a, Client>,
Read<'a, Settings>,
);
@ -41,18 +39,8 @@ impl<'a> VSystem<'a> for Sys {
fn run(
_job: &mut VJob<Self>,
(
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()
}
}

View File

@ -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<Self>>,
Write<'a, SysTimer<Self>>,
);
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();
}
}
}

View File

@ -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<Self>>,
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<Self>, (mut timer, comps, mut trackers): Self::SystemData) {
timer.start();
fn run(_job: &mut VJob<Self>, (comps, mut trackers): Self::SystemData) {
record_changes(&comps, &mut trackers);
timer.end();
}
}

View File

@ -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<Self>>,
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();
}
}

View File

@ -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<ServerEvent>>,
Read<'a, Tick>,
Write<'a, SysTimer<Self>>,
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()
}
}

View File

@ -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<Self>>,
ReadStorage<'a, Pos>,
ReadStorage<'a, Presence>,
ReadStorage<'a, Client>,
@ -30,10 +28,8 @@ impl<'a> VSystem<'a> for Sys {
fn run(
_job: &mut VJob<Self>,
(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();
}
}

View File

@ -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<Self>>,
);
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();
}
}

View File

@ -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>,

View File

@ -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>,