Improve chunk space consumption by a lot.

3x - 5x depending on terrain.  We can do a lot better but this is a good
start.

Also, added chunk group count to metrics.  This correlates with memory
usage specifically by chunk voxel data in a much more direct way than
chonk or chunk count do, so this should provide extra useful information
(especially for our average overhead per chonk / chunk).
This commit is contained in:
Joshua Yanovski 2020-09-28 13:35:49 +02:00
parent c8d7bf3aad
commit b9528da8f6
4 changed files with 22 additions and 0 deletions

View File

@ -65,6 +65,10 @@ impl<V, S: RectVolSize, M: Clone> Chonk<V, S, M> {
pub fn sub_chunks_len(&self) -> usize { self.sub_chunks.len() }
pub fn sub_chunk_groups(&self) -> usize {
self.sub_chunks.iter().map(SubChunk::num_groups).sum()
}
// Returns the index (in self.sub_chunks) of the SubChunk that contains
// layer z; note that this index changes when more SubChunks are prepended
fn sub_chunk_idx(&self, z: i32) -> i32 {
@ -126,6 +130,11 @@ impl<V: Clone + PartialEq, S: RectVolSize, M: Clone> WriteVol for Chonk<V, S, M>
self.z_offset += sub_chunk_idx * SubChunkSize::<S>::SIZE.z as i32;
sub_chunk_idx = 0;
} else if pos.z >= self.get_max_z() {
if self.sub_chunks.is_empty() && block == self.below {
// Try not to generate extra blocks unless necessary.
self.z_offset += 1;
return Ok(());
}
// Append exactly sufficiently many SubChunks via Vec::extend
let c = Chunk::<V, SubChunkSize<S>, M>::filled(self.above.clone(), self.meta.clone());
let n = 1 + sub_chunk_idx as usize - self.sub_chunks.len();

View File

@ -121,6 +121,8 @@ impl<V, S: VolSize, M> Chunk<V, S, M> {
/// Get a mutable reference to the internal metadata.
pub fn metadata_mut(&mut self) -> &mut M { &mut self.meta }
pub fn num_groups(&self) -> usize { self.vox.len() / Self::GROUP_VOLUME as usize }
#[inline(always)]
fn grp_idx(pos: Vec3<i32>) -> u32 {
let grp_pos = pos.map2(Self::GROUP_SIZE, |e, s| e as u32 / s);

View File

@ -720,12 +720,15 @@ impl Server {
.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);

View File

@ -45,6 +45,7 @@ pub struct ChunkGenMetrics {
pub struct TickMetrics {
pub chonks_count: IntGauge,
pub chunks_count: IntGauge,
pub chunk_groups_count: IntGauge,
pub entity_count: IntGauge,
pub tick_time: IntGaugeVec,
pub build_info: IntGauge,
@ -237,6 +238,10 @@ impl TickMetrics {
"chunks_count",
"number of all chunks currently active on the server",
))?;
let chunk_groups_count = IntGauge::with_opts(Opts::new(
"chunk_groups_count",
"number of 4×4×4 groups currently allocated by chunks on the server",
))?;
let entity_count = IntGauge::with_opts(Opts::new(
"entity_count",
"number of all entities currently active on the server",
@ -267,6 +272,7 @@ impl TickMetrics {
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();
@ -277,6 +283,7 @@ impl TickMetrics {
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))?;
@ -290,6 +297,7 @@ impl TickMetrics {
Self {
chonks_count,
chunks_count,
chunk_groups_count,
entity_count,
tick_time,
build_info,