put cache in ECS to get rid of allocations

This commit is contained in:
Marcel Märtens 2020-11-04 11:02:45 +01:00
parent ce3173ecdf
commit a7123c6e14
8 changed files with 52 additions and 36 deletions

View File

@ -6,8 +6,8 @@ rustflags = [
[alias]
generate = "run --package tools --"
test-server = "-Zpackage-features run --bin veloren-server-cli --no-default-features"
tracy-server = "-Zunstable-options -Zpackage-features run --bin veloren-server-cli --no-default-features --features tracy --profile releasedebuginfo"
tracy-server = "-Zunstable-options -Zpackage-features run --bin veloren-server-cli --no-default-features --features tracy --profile dev"
test-voxygen = "-Zpackage-features run --bin veloren-voxygen --no-default-features --features gl"
tracy-voxygen = "-Zunstable-options -Zpackage-features run --bin veloren-voxygen --no-default-features --features tracy,gl --profile releasedebuginfo"
tracy-voxygen = "-Zunstable-options -Zpackage-features run --bin veloren-voxygen --no-default-features --features tracy,gl --profile dev"
server = "run --bin veloren-server-cli"

View File

@ -54,7 +54,10 @@ pub use inventory::{
pub use last::Last;
pub use location::{Waypoint, WaypointArea};
pub use misc::Object;
pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
pub use phys::{
Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, PreviousVelDtCache, Scale,
Sticky, Vel,
};
pub use player::Player;
pub use projectile::Projectile;
pub use shockwave::{Shockwave, ShockwaveHitEntities};

View File

@ -32,6 +32,16 @@ impl Component for Ori {
type Storage = IdvStorage<Self>;
}
/// Cache of Velocity (of last tick) * dt (of curent tick)
/// It's updated and read in physics sys to speed up entity<->entity collisions
/// no need to send it via network
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct PreviousVelDtCache(pub Vec3<f32>);
impl Component for PreviousVelDtCache {
type Storage = IdvStorage<Self>;
}
// Scale
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct Scale(pub f32);

View File

@ -14,7 +14,6 @@ pub struct SysMetrics {
#[derive(Default)]
pub struct PhysicsMetrics {
pub velocities_cache_len: i64,
pub entity_entity_collision_checks: i64,
pub entity_entity_collisions: i64,
}

View File

@ -167,6 +167,7 @@ impl State {
ecs.register::<comp::group::Invite>();
ecs.register::<comp::group::PendingInvites>();
ecs.register::<comp::Beam>();
ecs.register::<comp::PreviousVelDtCache>();
// Register synced resources used by the ECS.
ecs.insert(TimeOfDay(0.0));

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
BeamSegment, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, Projectile, Scale,
Shockwave, Sticky, Vel,
BeamSegment, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, PreviousVelDtCache,
Projectile, Scale, Shockwave, Sticky, Vel,
},
event::{EventBus, ServerEvent},
metrics::{PhysicsMetrics, SysMetrics},
@ -66,6 +66,7 @@ impl<'a> System<'a> for Sys {
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
WriteStorage<'a, PreviousVelDtCache>,
ReadStorage<'a, Mounting>,
ReadStorage<'a, Projectile>,
ReadStorage<'a, BeamSegment>,
@ -93,6 +94,7 @@ impl<'a> System<'a> for Sys {
mut positions,
mut velocities,
mut orientations,
mut previous_velocities_times_dt,
mountings,
projectiles,
beams,
@ -133,25 +135,37 @@ impl<'a> System<'a> for Sys {
// terrain collision code below, although that's not trivial to do since
// it means the step needs to take into account the speeds of both
// entities.
span!(guard, "Clone pushback velocities");
//just prereserve for 1000 entities
let mut old_velocities_times_dt = Vec::with_capacity(1000);
for (entity, vel, _, _, _, _) in (
span!(guard, "Maintain pushback cache");
//Add PreviousVelDtCache for all relevant entities
for entity in (
&entities,
&velocities,
&positions,
!&previous_velocities_times_dt,
!&mountings,
!&beams,
!&shockwaves,
)
.join()
.map(|(e, _, _, _, _, _, _)| e)
.collect::<Vec<_>>()
{
let _ = previous_velocities_times_dt.insert(entity, PreviousVelDtCache(Vec3::zero()));
}
//Update PreviousVelDtCache
for (_, vel, _, mut vel_dt, _, _, _) in (
&entities,
&velocities,
&positions,
&mut previous_velocities_times_dt,
!&mountings,
!&beams,
!&shockwaves,
)
.join()
{
let id = entity.id() as usize;
let vel_dt = vel.0 * dt.0;
if id >= old_velocities_times_dt.len() {
old_velocities_times_dt.resize(id + 1, Vec3::zero());
}
old_velocities_times_dt[id] = vel_dt;
vel_dt.0 = vel.0 * dt.0;
}
drop(guard);
span!(guard, "Apply pushback");
@ -159,6 +173,7 @@ impl<'a> System<'a> for Sys {
&entities,
&positions,
&mut velocities,
&previous_velocities_times_dt,
scales.maybe(),
masses.maybe(),
colliders.maybe(),
@ -170,16 +185,16 @@ impl<'a> System<'a> for Sys {
projectiles.maybe(),
)
.par_join()
.filter(|(_, _, _, _, _, _, _, sticky, physics, _)| {
.filter(|(_, _, _, _, _, _, _, _, sticky, physics, _)| {
sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground)
})
.map(|(e, p, v, vd, s, m, c, _, _, ph, pr)| (e, p, v, vd, s, m, c, ph, pr))
.fold(PhysicsMetrics::default,
|mut metrics,(entity, pos, vel, scale, mass, collider, _, _, physics, projectile)| {
|mut metrics,(entity, pos, vel, vel_dt, scale, mass, collider, physics, projectile)| {
let scale = scale.map(|s| s.0).unwrap_or(1.0);
let radius = collider.map(|c| c.get_radius()).unwrap_or(0.5);
let z_limits = collider.map(|c| c.get_z_limits()).unwrap_or((-0.5, 0.5));
let mass = mass.map(|m| m.0).unwrap_or(scale);
let vel_dt = old_velocities_times_dt[entity.id() as usize];
// Resets touch_entities in physics
physics.touch_entities.clear();
@ -192,6 +207,7 @@ impl<'a> System<'a> for Sys {
entity_other,
other,
pos_other,
vel_dt_other,
scale_other,
mass_other,
collider_other,
@ -203,6 +219,7 @@ impl<'a> System<'a> for Sys {
&entities,
&uids,
&positions,
&previous_velocities_times_dt,
scales.maybe(),
masses.maybe(),
colliders.maybe(),
@ -222,10 +239,9 @@ impl<'a> System<'a> for Sys {
let collision_dist = scale * radius + scale_other * radius_other;
let collision_dist_sqr = collision_dist * collision_dist;
let vel_dt_other = old_velocities_times_dt[entity_other.id() as usize];
let pos_diff_squared = (pos.0 - pos_other.0).magnitude_squared();
let vel_diff_squared = (vel_dt - vel_dt_other).magnitude_squared();
let vel_diff_squared = (vel_dt.0 - vel_dt_other.0).magnitude_squared();
// Sanity check: don't try colliding entities that are too far from each
// other Note: I think this catches all cases. If
@ -256,8 +272,8 @@ impl<'a> System<'a> for Sys {
for i in 0..increments {
let factor = i as f32 * step_delta;
let pos = pos.0 + vel_dt * factor;
let pos_other = pos_other.0 + vel_dt_other * factor;
let pos = pos.0 + vel_dt.0 * factor;
let pos_other = pos_other.0 + vel_dt_other.0 * factor;
let diff = pos.xy() - pos_other.xy();
@ -293,12 +309,10 @@ impl<'a> System<'a> for Sys {
)
.reduce(PhysicsMetrics::default, |old, new| {
PhysicsMetrics {
velocities_cache_len: 0,
entity_entity_collision_checks: old.entity_entity_collision_checks + new.entity_entity_collision_checks,
entity_entity_collisions: old.entity_entity_collisions + new.entity_entity_collisions,
}
});
physics_metrics.velocities_cache_len = old_velocities_times_dt.len() as i64;
physics_metrics.entity_entity_collision_checks = metrics.entity_entity_collision_checks;
physics_metrics.entity_entity_collisions = metrics.entity_entity_collisions;
drop(guard);

View File

@ -788,9 +788,6 @@ impl Server {
.ecs()
.read_resource::<common::metrics::PhysicsMetrics>();
self.physics_metrics
.velocities_cache_len
.set(res.velocities_cache_len);
self.physics_metrics
.entity_entity_collision_checks_count
.inc_by(res.entity_entity_collision_checks);

View File

@ -18,7 +18,6 @@ use tracing::{debug, error};
type RegistryFn = Box<dyn FnOnce(&Registry) -> Result<(), prometheus::Error>>;
pub struct PhysicsMetrics {
pub velocities_cache_len: IntGauge,
pub entity_entity_collision_checks_count: IntCounter,
pub entity_entity_collisions_count: IntCounter,
}
@ -70,10 +69,6 @@ pub struct ServerMetrics {
impl PhysicsMetrics {
pub fn new() -> Result<(Self, RegistryFn), prometheus::Error> {
let velocities_cache_len = IntGauge::with_opts(Opts::new(
"velocities_cache_len",
"shows the size of the velocities_cache in entries",
))?;
let entity_entity_collision_checks_count = IntCounter::with_opts(Opts::new(
"entity_entity_collision_checks_count",
"shows the number of collision checks",
@ -83,13 +78,11 @@ impl PhysicsMetrics {
"shows the number of actual collisions detected",
))?;
let velocities_cache_len_clone = velocities_cache_len.clone();
let entity_entity_collision_checks_count_clone =
entity_entity_collision_checks_count.clone();
let entity_entity_collisions_count_clone = entity_entity_collisions_count.clone();
let f = |registry: &Registry| {
registry.register(Box::new(velocities_cache_len_clone))?;
registry.register(Box::new(entity_entity_collision_checks_count_clone))?;
registry.register(Box::new(entity_entity_collisions_count_clone))?;
Ok(())
@ -97,7 +90,6 @@ impl PhysicsMetrics {
Ok((
Self {
velocities_cache_len,
entity_entity_collision_checks_count,
entity_entity_collisions_count,
},