mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add more profiling spans to Server startup related things in order to
visualize where time is being spent. Make `Lod::from_world` use the same rayon pool as other things during the server startup. Move parallel iteration up out of structure_gen.par_iter in order to slightly optimize Lod::from_world (saves a few hundred milliseconds on my machine)
This commit is contained in:
parent
92a42ced18
commit
c6f5e8dac2
@ -3,6 +3,7 @@ use super::{
|
||||
vec2_as_uniform_idx, TerrainChunkSize, NEIGHBOR_DELTA, TERRAIN_CHUNK_BLOCKS_LG,
|
||||
};
|
||||
use crate::vol::RectVolSize;
|
||||
use common_base::prof_span;
|
||||
use core::{f32, f64, iter, ops::RangeInclusive};
|
||||
use vek::*;
|
||||
|
||||
@ -451,6 +452,7 @@ impl<'a> MapConfig<'a> {
|
||||
sample_wpos: impl Fn(Vec2<i32>) -> f32,
|
||||
mut write_pixel: impl FnMut(Vec2<usize>, (u8, u8, u8, u8)),
|
||||
) -> MapDebug {
|
||||
prof_span!("MapConfig::generate");
|
||||
let MapConfig {
|
||||
map_size_lg,
|
||||
dimensions,
|
||||
|
@ -24,7 +24,7 @@ use common::{
|
||||
vol::{ReadVol, WriteVol},
|
||||
weather::{Weather, WeatherGrid},
|
||||
};
|
||||
use common_base::span;
|
||||
use common_base::{prof_span, span};
|
||||
use common_ecs::{PhysicsMetrics, SysMetrics};
|
||||
use common_net::sync::{interpolation as sync_interp, WorldSyncExt};
|
||||
use core::{convert::identity, time::Duration};
|
||||
@ -179,6 +179,7 @@ impl State {
|
||||
map_size_lg: MapSizeLg,
|
||||
default_chunk: Arc<TerrainChunk>,
|
||||
) -> specs::World {
|
||||
prof_span!("State::setup_ecs_world");
|
||||
let mut ecs = specs::World::new();
|
||||
// Uids for sync
|
||||
ecs.register_sync_marker();
|
||||
|
@ -284,6 +284,8 @@ impl Server {
|
||||
default_chunk: Arc::new(world.generate_oob_chunk()),
|
||||
};
|
||||
|
||||
let lod = lod::Lod::from_world(&world, index.as_index_ref(), &pools);
|
||||
|
||||
let mut state = State::server(
|
||||
pools,
|
||||
world.sim().map_size_lg(),
|
||||
@ -455,7 +457,7 @@ impl Server {
|
||||
state.ecs_mut().insert(Arc::clone(&world));
|
||||
state
|
||||
.ecs_mut()
|
||||
.insert(lod::Lod::from_world(&world, index.as_index_ref()));
|
||||
.insert(lod);
|
||||
state.ecs_mut().insert(index.clone());
|
||||
|
||||
// Set starting time for the server.
|
||||
|
@ -17,19 +17,23 @@ pub struct Lod {
|
||||
|
||||
impl Lod {
|
||||
#[cfg(feature = "worldgen")]
|
||||
pub fn from_world(world: &World, index: IndexRef) -> Self {
|
||||
let mut zones = HashMap::new();
|
||||
pub fn from_world(world: &World, index: IndexRef, threadpool: &rayon::ThreadPool) -> Self {
|
||||
common_base::prof_span!("Lod::from_world");
|
||||
threadpool.install(|| {
|
||||
let zone_sz = (world.sim().get_size() + lod::ZONE_SIZE - 1) / lod::ZONE_SIZE;
|
||||
|
||||
let zone_sz = (world.sim().get_size() + lod::ZONE_SIZE - 1) / lod::ZONE_SIZE;
|
||||
use rayon::prelude::*;
|
||||
let zones = (0..zone_sz.x)
|
||||
.into_par_iter()
|
||||
.flat_map(|i| (0..zone_sz.y).into_par_iter().map(move |j| (i, j)))
|
||||
.map(|(i, j)| {
|
||||
let zone_pos = Vec2::new(i, j).map(|e| e as i32);
|
||||
(zone_pos, world.get_lod_zone(zone_pos, index))
|
||||
})
|
||||
.collect();
|
||||
|
||||
for i in 0..zone_sz.x {
|
||||
for j in 0..zone_sz.y {
|
||||
let zone_pos = Vec2::new(i, j).map(|e| e as i32);
|
||||
zones.insert(zone_pos, world.get_lod_zone(zone_pos, index));
|
||||
}
|
||||
}
|
||||
|
||||
Self { zones }
|
||||
Self { zones }
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "worldgen"))]
|
||||
|
@ -275,6 +275,7 @@ impl Civs {
|
||||
//=== old economy is gone
|
||||
|
||||
// Flatten ground around sites
|
||||
prof_span!(guard, "Flatten ground around sites");
|
||||
for site in this.sites.values() {
|
||||
let wpos = site.center * TerrainChunkSize::RECT_SIZE.map(|e: u32| e as i32);
|
||||
|
||||
@ -339,8 +340,10 @@ impl Civs {
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(guard);
|
||||
|
||||
// Place sites in world
|
||||
prof_span!(guard, "Place sites in world");
|
||||
let mut cnt = 0;
|
||||
for sim_site in this.sites.values_mut() {
|
||||
cnt += 1;
|
||||
@ -436,6 +439,7 @@ impl Civs {
|
||||
}
|
||||
debug!(?sim_site.center, "Placed site at location");
|
||||
}
|
||||
drop(guard);
|
||||
info!(?cnt, "all sites placed");
|
||||
|
||||
//this.display_info();
|
||||
@ -465,23 +469,25 @@ impl Civs {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this looks optimizable
|
||||
|
||||
// collect natural resources
|
||||
prof_span!(guard, "collect natural resources");
|
||||
let sites = &mut index.sites;
|
||||
(0..ctx.sim.map_size_lg().chunks_len())
|
||||
.into_iter()
|
||||
.for_each(|posi| {
|
||||
let chpos = uniform_idx_as_vec2(ctx.sim.map_size_lg(), posi);
|
||||
let wpos = chpos.map(|e| e as i64) * TerrainChunkSize::RECT_SIZE.map(|e| e as i64);
|
||||
let closest_site = (*sites)
|
||||
.iter_mut()
|
||||
.filter(|s| !matches!(s.1.kind, crate::site::SiteKind::Dungeon(_)))
|
||||
.min_by_key(|(_id, s)| s.get_origin().map(|e| e as i64).distance_squared(wpos));
|
||||
if let Some((_id, s)) = closest_site {
|
||||
let distance_squared = s.get_origin().map(|e| e as i64).distance_squared(wpos);
|
||||
s.economy
|
||||
.add_chunk(ctx.sim.get(chpos).unwrap(), distance_squared);
|
||||
}
|
||||
});
|
||||
(0..ctx.sim.map_size_lg().chunks_len()).for_each(|posi| {
|
||||
let chpos = uniform_idx_as_vec2(ctx.sim.map_size_lg(), posi);
|
||||
let wpos = chpos.map(|e| e as i64) * TerrainChunkSize::RECT_SIZE.map(|e| e as i64);
|
||||
let closest_site = (*sites)
|
||||
.iter_mut()
|
||||
.filter(|s| !matches!(s.1.kind, crate::site::SiteKind::Dungeon(_)))
|
||||
.min_by_key(|(_id, s)| s.get_origin().map(|e| e as i64).distance_squared(wpos));
|
||||
if let Some((_id, s)) = closest_site {
|
||||
let distance_squared = s.get_origin().map(|e| e as i64).distance_squared(wpos);
|
||||
s.economy
|
||||
.add_chunk(ctx.sim.get(chpos).unwrap(), distance_squared);
|
||||
}
|
||||
});
|
||||
drop(guard);
|
||||
sites
|
||||
.iter_mut()
|
||||
.for_each(|(_, s)| s.economy.cache_economy());
|
||||
|
@ -60,7 +60,6 @@ use common_net::msg::{world_msg, WorldMapMsg};
|
||||
use enum_map::EnumMap;
|
||||
use rand::{prelude::*, Rng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use serde::Deserialize;
|
||||
use std::time::Duration;
|
||||
use vek::*;
|
||||
@ -138,6 +137,7 @@ impl World {
|
||||
}
|
||||
|
||||
pub fn get_map_data(&self, index: IndexRef, threadpool: &rayon::ThreadPool) -> WorldMapMsg {
|
||||
prof_span!("World::get_map_data");
|
||||
threadpool.install(|| {
|
||||
// we need these numbers to create unique ids for cave ends
|
||||
let num_sites = self.civs().sites().count() as u64;
|
||||
@ -564,6 +564,7 @@ impl World {
|
||||
let mut objects = Vec::new();
|
||||
|
||||
// Add trees
|
||||
prof_span!(guard, "add trees");
|
||||
objects.append(
|
||||
&mut self
|
||||
.sim()
|
||||
@ -602,6 +603,7 @@ impl World {
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
drop(guard);
|
||||
|
||||
// Add buildings
|
||||
objects.extend(
|
||||
|
@ -51,6 +51,7 @@ use common::{
|
||||
},
|
||||
vol::RectVolSize,
|
||||
};
|
||||
use common_base::prof_span;
|
||||
use common_net::msg::WorldMapMsg;
|
||||
use noise::{
|
||||
BasicMulti, Billow, Fbm, HybridMulti, MultiFractal, NoiseFn, RangeFunction, RidgedMulti,
|
||||
@ -668,6 +669,7 @@ pub struct WorldSim {
|
||||
|
||||
impl WorldSim {
|
||||
pub fn generate(seed: u32, opts: WorldOpts, threadpool: &rayon::ThreadPool) -> Self {
|
||||
prof_span!("WorldSim::generate");
|
||||
let calendar = opts.calendar; // separate lifetime of elements
|
||||
let world_file = opts.world_file;
|
||||
|
||||
@ -1586,6 +1588,7 @@ impl WorldSim {
|
||||
/// Draw a map of the world based on chunk information. Returns a buffer of
|
||||
/// u32s.
|
||||
pub fn get_map(&self, index: IndexRef, calendar: Option<&Calendar>) -> WorldMapMsg {
|
||||
prof_span!("WorldSim::get_map");
|
||||
let mut map_config = MapConfig::orthographic(
|
||||
self.map_size_lg(),
|
||||
core::ops::RangeInclusive::new(CONFIG.sea_level, CONFIG.sea_level + self.max_height),
|
||||
@ -1603,6 +1606,7 @@ impl WorldSim {
|
||||
};
|
||||
|
||||
let samples_data = {
|
||||
prof_span!("samples data");
|
||||
let column_sample = ColumnGen::new(self);
|
||||
(0..self.map_size_lg().chunks_len())
|
||||
.into_par_iter()
|
||||
@ -2293,10 +2297,10 @@ impl WorldSim {
|
||||
&self,
|
||||
wpos_min: Vec2<i32>,
|
||||
wpos_max: Vec2<i32>,
|
||||
) -> impl ParallelIterator<Item = TreeAttr> + '_ {
|
||||
) -> impl Iterator<Item = TreeAttr> + '_ {
|
||||
self.gen_ctx
|
||||
.structure_gen
|
||||
.par_iter(wpos_min, wpos_max)
|
||||
.iter(wpos_min, wpos_max)
|
||||
.filter_map(move |(wpos, seed)| {
|
||||
let lottery = self.make_forest_lottery(wpos);
|
||||
Some(TreeAttr {
|
||||
|
@ -3,6 +3,7 @@ use common::{
|
||||
terrain::{neighbors, uniform_idx_as_vec2, vec2_as_uniform_idx, MapSizeLg, TerrainChunkSize},
|
||||
vol::RectVolSize,
|
||||
};
|
||||
use common_base::prof_span;
|
||||
use noise::{MultiFractal, NoiseFn, Perlin, Seedable};
|
||||
use num::Float;
|
||||
use rayon::prelude::*;
|
||||
@ -374,6 +375,7 @@ pub fn get_horizon_map<F: Float + Sync, A: Send, H: Send>(
|
||||
to_angle: impl Fn(F) -> A + Sync,
|
||||
to_height: impl Fn(F) -> H + Sync,
|
||||
) -> Result<[HorizonMap<A, H>; 2], ()> {
|
||||
prof_span!("get_horizon_map");
|
||||
if maxh < minh {
|
||||
// maxh must be greater than minh
|
||||
return Err(());
|
||||
|
@ -1,3 +1,7 @@
|
||||
use crate::{sim::WorldSim, site::economy::simulate_economy, Index};
|
||||
use common_base::prof_span;
|
||||
|
||||
pub fn simulate(index: &mut Index, _world: &mut WorldSim) { simulate_economy(index); }
|
||||
pub fn simulate(index: &mut Index, _world: &mut WorldSim) {
|
||||
prof_span!("sim2::simulate");
|
||||
simulate_economy(index);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use super::{RandomField, Sampler};
|
||||
use rayon::prelude::*;
|
||||
use vek::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -69,11 +68,7 @@ impl StructureGen2d {
|
||||
|
||||
/// Note: Generates all possible closest samples for elements in the range
|
||||
/// of min to max, *exclusive.*
|
||||
pub fn par_iter(
|
||||
&self,
|
||||
min: Vec2<i32>,
|
||||
max: Vec2<i32>,
|
||||
) -> impl ParallelIterator<Item = StructureField> {
|
||||
pub fn iter(&self, min: Vec2<i32>, max: Vec2<i32>) -> impl Iterator<Item = StructureField> {
|
||||
let freq = self.freq;
|
||||
let spread = self.spread;
|
||||
let spread_mul = Self::spread_mul(spread);
|
||||
@ -102,7 +97,7 @@ impl StructureGen2d {
|
||||
let x_field = self.x_field;
|
||||
let y_field = self.y_field;
|
||||
let seed_field = self.seed_field;
|
||||
(0..len).into_par_iter().map(move |xy| {
|
||||
(0..len).map(move |xy| {
|
||||
let index = min_index + Vec2::new((xy % xlen as u64) as i32, (xy / xlen as u64) as i32);
|
||||
Self::index_to_sample_internal(
|
||||
freq,
|
||||
|
Loading…
Reference in New Issue
Block a user