From f3369dccfc45390595df1b80ece97b3d211aab3d Mon Sep 17 00:00:00 2001 From: proller Date: Wed, 11 Sep 2024 16:57:47 +0000 Subject: [PATCH 1/2] wip --- src/clientiface.h | 3 ++- src/fm_clientiface.cpp | 2 +- src/fm_liquid.cpp | 41 ++++++++++++++++++++--------------------- src/map.cpp | 1 - src/map.h | 2 +- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/clientiface.h b/src/clientiface.h index 4d0bbb786..55edc7cf7 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -311,6 +311,7 @@ class RemoteClient bool isBlockSent(v3s16 p) const { + const auto lock = m_blocks_sent.lock_shared_rec(); return m_blocks_sent.find(p) != m_blocks_sent.end(); } @@ -408,7 +409,7 @@ class RemoteClient No MapBlock* is stored here because the blocks can get deleted. */ unsigned int m_nearest_unsent_reset_want = 0; - concurrent_shared_unordered_map m_blocks_sent; + concurrent_unordered_map m_blocks_sent; //std::unordered_set m_blocks_sent; diff --git a/src/fm_clientiface.cpp b/src/fm_clientiface.cpp index f1a966dfd..ae62d1dd5 100644 --- a/src/fm_clientiface.cpp +++ b/src/fm_clientiface.cpp @@ -326,7 +326,7 @@ int RemoteClient::GetNextBlocks(ServerEnvironment *env, EmergeManager *emerge, */ double block_sent = 0; { - auto lock = m_blocks_sent.lock_shared_rec(); + const auto lock = m_blocks_sent.lock_shared_rec(); block_sent = m_blocks_sent.contains(p) ? m_blocks_sent.get(p) : 0; } diff --git a/src/fm_liquid.cpp b/src/fm_liquid.cpp index aa0bca78f..b40a4003b 100644 --- a/src/fm_liquid.cpp +++ b/src/fm_liquid.cpp @@ -19,21 +19,20 @@ You should have received a copy of the GNU General Public License along with Freeminer. If not, see . */ -#include -#include -#include +#include "emerge.h" +#include "gamedef.h" #include "irr_v3d.h" +#include "log_types.h" #include "map.h" -#include "gamedef.h" -#include "scripting_server.h" -#include "settings.h" #include "nodedef.h" -#include "log_types.h" -#include "server.h" -// #include "scripting_game.h" #include "profiler.h" -#include "emerge.h" +#include "scripting_server.h" +#include "server.h" +#include "settings.h" #include "util/unordered_map_hash.h" +#include +#include +#include #define LIQUID_DEBUG 0 @@ -190,9 +189,8 @@ NEXT_LIQUID:; nb.drop = 0; if (!nb.node) { - // if (i == D_SELF && (loopcount % 2) && initial_size < m_liquid_step_flow - // * 3) must_reflow_third[nb.pos] = 1; - // must_reflow_third.push_back(nb.pos); + //if (i == D_SELF && (loopcount % 8) && initial_size < m_liquid_step_flow * 3) // must_reflow_third[nb.pos] = 1; + // must_reflow_third.emplace_back(nb.pos); continue; } @@ -296,8 +294,8 @@ NEXT_LIQUID:; setNode(neighbors[D_BOTTOM].pos, neighbors[D_SELF].node); // must_reflow_second[neighbors[D_SELF].pos] = 1; // must_reflow_second[neighbors[D_BOTTOM].pos] = 1; - must_reflow_second.push_back(neighbors[D_SELF].pos); - must_reflow_second.push_back(neighbors[D_BOTTOM].pos); + must_reflow_second.emplace_back(neighbors[D_SELF].pos); + must_reflow_second.emplace_back(neighbors[D_BOTTOM].pos); #if LIQUID_DEBUG infostream << "Liquid swap1" << neighbors[D_SELF].pos << nodemgr->get(neighbors[D_SELF].node).name @@ -316,8 +314,8 @@ NEXT_LIQUID:; setNode(neighbors[D_TOP].pos, neighbors[D_SELF].node); // must_reflow_second[neighbors[D_SELF].pos] = 1; // must_reflow_second[neighbors[D_TOP].pos] = 1; - must_reflow_second.push_back(neighbors[D_SELF].pos); - must_reflow_second.push_back(neighbors[D_TOP].pos); + must_reflow_second.emplace_back(neighbors[D_SELF].pos); + must_reflow_second.emplace_back(neighbors[D_TOP].pos); #if LIQUID_DEBUG infostream << "Liquid swap2" << neighbors[D_TOP].pos << nodemgr->get(neighbors[D_TOP].node).name @@ -740,7 +738,7 @@ NEXT_LIQUID:; for (uint8_t ir = D_SELF + 1; ir < D_TOP; ++ir) { // only same level uint8_t ii = liquid_random_map[(loopcount + loop_rand + 5) % 4][ir]; if (neighbors[ii].liquid) - must_reflow_second.push_back( + must_reflow_second.emplace_back( neighbors[i].pos + liquid_flow_dirs[ii]); // must_reflow_second[neighbors[i].pos + liquid_flow_dirs[ii]] = 1; } @@ -775,8 +773,9 @@ NEXT_LIQUID:; blocks_lighting_update.emplace(blockpos); } // fmtodo: make here random %2 or.. - if (total_level < level_max * can_liquid) - must_reflow.push_back(neighbors[i].pos); + if (total_level < level_max * can_liquid) { + must_reflow.emplace_back(neighbors[i].pos); + } } if (fall_down) { @@ -842,7 +841,7 @@ NEXT_LIQUID:; } for (const auto &blockpos : blocks_lighting_update) { - MapBlock *block = + auto block = getBlockNoCreateNoEx(blockpos, true); // remove true if light bugs if (!block) continue; diff --git a/src/map.cpp b/src/map.cpp index 7334a9048..822e31ce1 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -73,7 +73,6 @@ Map::Map(IGameDef *gamedef): m_gamedef(gamedef), m_nodedef(gamedef->ndef()) { - m_liquid_step_flow = 1000; time_life = 0; getBlockCacheFlush(); } diff --git a/src/map.h b/src/map.h index 595b46f58..db8c7d337 100644 --- a/src/map.h +++ b/src/map.h @@ -282,7 +282,7 @@ class Map : public NodeContainer MapNode getNodeTry(const v3pos_t &p); //MapNode getNodeNoLock(v3s16 p); // dont use - std::atomic_uint m_liquid_step_flow{0}; + std::atomic_uint m_liquid_step_flow{1000}; virtual s16 getHeat(const v3pos_t &p, bool no_random = 0); virtual s16 getHumidity(const v3pos_t &p, bool no_random = 0); From 730caaeaba4aae87c0c1602cd9165250f72e49c7 Mon Sep 17 00:00:00 2001 From: proller Date: Wed, 11 Sep 2024 23:47:37 +0200 Subject: [PATCH 2/2] wip --- src/fm_liquid.cpp | 79 +++++++++++++++++++++++++++++--------------- src/fm_server.cpp | 19 ++++++----- src/map.h | 1 + src/util/container.h | 2 +- 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/fm_liquid.cpp b/src/fm_liquid.cpp index b40a4003b..ce3107b8e 100644 --- a/src/fm_liquid.cpp +++ b/src/fm_liquid.cpp @@ -106,10 +106,10 @@ size_t ServerMap::transformLiquidsReal(Server *m_server, unsigned int max_cycle_ const auto *nodemgr = m_nodedef; // TimeTaker timer("transformLiquidsReal()"); - uint32_t loopcount = 0; + size_t loopcount = 0; const auto initial_size = transforming_liquid_size(); - int32_t regenerated = 0; + size_t regenerated = 0; #if LIQUID_DEBUG bool debug = 1; @@ -132,19 +132,29 @@ size_t ServerMap::transformLiquidsReal(Server *m_server, unsigned int max_cycle_ const auto end_ms = porting::getTimeMs() + max_cycle_ms; -NEXT_LIQUID:; - while (transforming_liquid_size() > 0) { + { + std::lock_guard lock(m_transforming_liquid_mutex); + m_transforming_liquid_local.reserve(initial_size); + while (!m_transforming_liquid.m_queue.empty()) { + m_transforming_liquid_local.emplace_back( + m_transforming_liquid.m_queue.front()); + m_transforming_liquid.m_queue.pop(); + } + m_transforming_liquid.m_set.clear(); + } + + for (const auto &p0 : m_transforming_liquid_local) { // This should be done here so that it is done when continue is used - if (loopcount >= initial_size * 2 || porting::getTimeMs() > end_ms) - break; + //if (loopcount >= initial_size * 2 || porting::getTimeMs() > end_ms) + // break; ++loopcount; /* Get a queued transforming liquid node */ - v3pos_t p0; + //v3pos_t p0; { // MutexAutoLock lock(m_transforming_liquid_mutex); - p0 = transforming_liquid_pop(); + // p0 = transforming_liquid_pop(); } int16_t total_level = 0; // u16 level_max = 0; @@ -167,6 +177,7 @@ NEXT_LIQUID:; /* Collect information about the environment, start from self */ + bool want_continue = false; for (uint8_t e = D_BOTTOM; e <= D_TOP; e++) { uint8_t i = liquid_explore_map[e]; NodeNeighbor &nb = neighbors[i]; @@ -306,7 +317,8 @@ NEXT_LIQUID:; << neighbors[D_BOTTOM].node << " w=" << neighbors[D_BOTTOM].weight << std::endl; #endif - goto NEXT_LIQUID; + want_continue = true; + break; } if (e == 2 && neighbors[D_SELF].weight && neighbors[D_TOP].weight > neighbors[D_SELF].weight) { @@ -326,7 +338,8 @@ NEXT_LIQUID:; << neighbors[D_SELF].node << " w=" << neighbors[D_SELF].weight << std::endl; #endif - goto NEXT_LIQUID; + want_continue = true; + break; } } catch (const InvalidPositionException &e) { verbosestream @@ -360,6 +373,8 @@ NEXT_LIQUID:; << std::endl; #endif } + if (want_continue) + continue; if (liquid_kind == CONTENT_IGNORE || !neighbors[D_SELF].liquid || total_level <= 0) @@ -404,7 +419,8 @@ NEXT_LIQUID:; ++falling[bpos]; fall_down = true; if (m_server->getEnv().nodeUpdate(neighbors[D_SELF].pos, 2)) { - goto NEXT_LIQUID; + want_continue = true; + break; } else { falling[bpos] += 100; } @@ -801,9 +817,11 @@ NEXT_LIQUID:; }*/ // g_profiler->graphAdd("liquids", 1); } + m_transforming_liquid_local.clear(); - uint32_t ret = loopcount >= initial_size ? 0 : transforming_liquid_size(); - if (ret || loopcount > m_liquid_step_flow) + //size_t ret = loopcount >= initial_size ? 0 : transforming_liquid_size(); + //if (ret || loopcount > m_liquid_step_flow) + if (porting::getTimeMs() > end_ms) m_liquid_step_flow += (m_liquid_step_flow > loopcount ? -1 : 1) * (int)loopcount / 10; /* @@ -822,27 +840,35 @@ NEXT_LIQUID:; { // TimeTaker timer13("transformLiquidsReal() reflow"); // auto lock = m_transforming_liquid.lock_unique_rec(); - std::lock_guard lock(m_transforming_liquid_mutex); + //std::lock_guard lock(m_transforming_liquid_mutex); // m_transforming_liquid.insert(must_reflow.begin(), must_reflow.end()); - for (const auto &p : must_reflow) - m_transforming_liquid.push_back(p); + std::unordered_set uniq; + m_transforming_liquid_local.reserve(must_reflow.size() + + must_reflow_second.size() + + must_reflow_third.size()); + for (const auto &p : must_reflow) { + if (!uniq.contains(p)) + m_transforming_liquid_local.emplace_back(p); + uniq.emplace(p); + } must_reflow.clear(); - // m_transforming_liquid.insert(must_reflow_second.begin(), - // must_reflow_second.end()); - for (const auto &p : must_reflow_second) - m_transforming_liquid.push_back(p); + for (const auto &p : must_reflow_second) { + if (!uniq.contains(p)) + m_transforming_liquid_local.emplace_back(p); + uniq.emplace(p); + } must_reflow_second.clear(); - // m_transforming_liquid.insert(must_reflow_third.begin(), - // must_reflow_third.end()); - for (const auto &p : must_reflow_third) - m_transforming_liquid.push_back(p); + for (const auto &p : must_reflow_third) { + if (!uniq.contains(p)) + m_transforming_liquid_local.emplace_back(p); + uniq.emplace(p); + } must_reflow_third.clear(); } for (const auto &blockpos : blocks_lighting_update) { - auto block = - getBlockNoCreateNoEx(blockpos, true); // remove true if light bugs + auto block = getBlockNoCreateNoEx(blockpos, true); // remove true if light bugs if (!block) continue; block->setLightingComplete(0); @@ -859,6 +885,7 @@ NEXT_LIQUID:; if (loopcount < initial_size) g_profiler->add("Server: liquids queue", initial_size); */ + g_profiler->avg("Server: liquids queue internal", m_transforming_liquid_local.size()); return loopcount; } diff --git a/src/fm_server.cpp b/src/fm_server.cpp index b32f3d5fd..d929f730f 100644 --- a/src/fm_server.cpp +++ b/src/fm_server.cpp @@ -234,16 +234,19 @@ class LiquidThread : public thread_vector while (!stopRequested()) { try { m_server->getEnv().getMap().getBlockCacheFlush(); - auto time_start = porting::getTimeMs(); + const auto time_start = porting::getTimeMs(); m_server->getEnv().getMap().getBlockCacheFlush(); std::map modified_blocks; // not used by fm - m_server->getEnv().getServerMap().transformLiquids( + const auto processed = m_server->getEnv().getServerMap().transformLiquids( modified_blocks, &m_server->getEnv(), m_server, max_cycle_ms); - auto time_spend = porting::getTimeMs() - time_start; + const auto time_spend = porting::getTimeMs() - time_start; - thread_local const auto static liquid_step = g_settings->getBool("liquid_step"); - std::this_thread::sleep_for(std::chrono::milliseconds( - time_spend > liquid_step ? 1 : liquid_step - time_spend)); + thread_local const auto static liquid_step = + g_settings->getBool("liquid_step"); + const auto sleep = + (processed < 10 ? 100 : 3) + + (time_spend > liquid_step ? 1 : liquid_step - time_spend); + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); #if !EXCEPTION_DEBUG } catch (const std::exception &e) { @@ -517,9 +520,7 @@ class AbmWorldThread : public thread_vector } try { const auto load_block = [&](const v3bpos_t &pos) -> MapBlockP { - auto block = - m_server->getEnv().getServerMap().getBlock( - pos); + auto block = m_server->getEnv().getServerMap().getBlock(pos); if (block) { return block; } diff --git a/src/map.h b/src/map.h index db8c7d337..461551ecd 100644 --- a/src/map.h +++ b/src/map.h @@ -425,6 +425,7 @@ class ServerMap : public Map v3pos_t transforming_liquid_pop(); void transforming_liquid_add(const v3pos_t &p); size_t transformLiquidsReal(Server *m_server, const unsigned int max_cycle_ms); + std::vector m_transforming_liquid_local; //getSurface level starting on basepos.y up to basepos.y + searchup //returns basepos.y -1 if no surface has been found diff --git a/src/util/container.h b/src/util/container.h index a4e020b00..114f61cbf 100644 --- a/src/util/container.h +++ b/src/util/container.h @@ -74,7 +74,7 @@ class UniqueQueue { return m_queue.size(); } -private: +//private: std::unordered_set m_set; std::queue m_queue; };