From 31a11a6df4922b590a50a5ff3d3c00d42a45599d Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Mon, 23 Jul 2018 19:12:51 +0100 Subject: Optimise chunk set (#4260) Closes #1244 Initially I was just going to add the cChunkData to cSetChunkData but profiling revealed that the copying wasn't even the biggest slowdown. Much more time was being spent in cChunk::CreateBlockEntities and cChunk::WakeUpSimulators than was in memcpy so I've made those significantly faster as well. Optimisations performed: * cSetChunkData now stores blocks in a cChunkData object * cChunkData objects can now perform moves even if they are using different pools * cChunk::CreateBlockEntities now iterates in the correct order and only over present chunk sections * Similarly for cChunk::WakeUpSimulators * cSetChunkData::CalculateHeightMap now shortcuts to the highest present chunk section before checking blocks directly --- src/SetChunkData.cpp | 56 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'src/SetChunkData.cpp') diff --git a/src/SetChunkData.cpp b/src/SetChunkData.cpp index c218c361c..1fdc2e775 100644 --- a/src/SetChunkData.cpp +++ b/src/SetChunkData.cpp @@ -8,6 +8,17 @@ #include "BlockEntities/BlockEntity.h" #include "Entities/Entity.h" +namespace +{ +struct sMemCallbacks: + cAllocationPool::cStarvationCallbacks +{ + virtual void OnStartUsingReserve() override {} + virtual void OnEndUsingReserve() override {} + virtual void OnOutOfReserve() override {} +}; +} // namespace (anonymous) + @@ -15,6 +26,8 @@ cSetChunkData::cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), + m_Pool(cpp14::make_unique(), cChunkData::NumSections), + m_ChunkData(m_Pool), m_IsLightValid(false), m_IsHeightMapValid(false), m_AreBiomesValid(false), @@ -38,29 +51,23 @@ cSetChunkData::cSetChunkData( cBlockEntities && a_BlockEntities, bool a_ShouldMarkDirty ) : - m_ChunkX(a_ChunkX), - m_ChunkZ(a_ChunkZ), - m_ShouldMarkDirty(a_ShouldMarkDirty) + cSetChunkData(a_ChunkX, a_ChunkZ, a_ShouldMarkDirty) { // Check the params' validity: ASSERT(a_BlockTypes != nullptr); ASSERT(a_BlockMetas != nullptr); // Copy block types and metas: - memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes)); - memcpy(m_BlockMetas, a_BlockMetas, sizeof(cChunkDef::BlockNibbles)); + m_ChunkData.SetBlockTypes(a_BlockTypes); + m_ChunkData.SetMetas(a_BlockMetas); // Copy lights, if both given: if ((a_BlockLight != nullptr) && (a_SkyLight != nullptr)) { - memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight)); - memcpy(m_SkyLight, a_SkyLight, sizeof(m_SkyLight)); + m_ChunkData.SetBlockLight(a_BlockLight); + m_ChunkData.SetSkyLight(a_SkyLight); m_IsLightValid = true; } - else - { - m_IsLightValid = false; - } // Copy the heightmap, if available: if (a_HeightMap != nullptr) @@ -68,10 +75,6 @@ cSetChunkData::cSetChunkData( memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap)); m_IsHeightMapValid = true; } - else - { - m_IsHeightMapValid = false; - } // Copy biomes, if available: if (a_Biomes != nullptr) @@ -79,10 +82,6 @@ cSetChunkData::cSetChunkData( memcpy(m_Biomes, a_Biomes, sizeof(m_Biomes)); m_AreBiomesValid = true; } - else - { - m_AreBiomesValid = false; - } // Move entities and blockentities: m_Entities = std::move(a_Entities); @@ -95,14 +94,25 @@ cSetChunkData::cSetChunkData( void cSetChunkData::CalculateHeightMap(void) { + // Find the heighest present section in the chunk + size_t MaxSection = 0; + for (size_t i = cChunkData::NumSections - 1; i != 0; --i) + { + if (m_ChunkData.GetSection(i) != nullptr) + { + MaxSection = i; + break; + } + } + const int MaxHeight = static_cast(MaxSection + 1) * cChunkData::SectionHeight - 1; + for (int x = 0; x < cChunkDef::Width; x++) { for (int z = 0; z < cChunkDef::Width; z++) { - for (int y = cChunkDef::Height - 1; y > -1; y--) + for (int y = MaxHeight; y > -1; y--) { - int index = cChunkDef::MakeIndexNoCheck(x, y, z); - if (m_BlockTypes[index] != E_BLOCK_AIR) + if (m_ChunkData.GetBlock({x, y, z}) != E_BLOCK_AIR) { m_HeightMap[x + z * cChunkDef::Width] = static_cast(y); break; @@ -124,7 +134,7 @@ void cSetChunkData::RemoveInvalidBlockEntities(void) { cBlockEntity * BlockEntity = itr->second; BLOCKTYPE EntityBlockType = BlockEntity->GetBlockType(); - BLOCKTYPE WorldBlockType = cChunkDef::GetBlock(m_BlockTypes, BlockEntity->GetRelX(), BlockEntity->GetPosY(), BlockEntity->GetRelZ()); + BLOCKTYPE WorldBlockType = m_ChunkData.GetBlock({BlockEntity->GetRelX(), BlockEntity->GetPosY(), BlockEntity->GetRelZ()}); if (EntityBlockType != WorldBlockType) { // Bad blocktype, remove the block entity: -- cgit v1.2.3