diff options
author | Lars Hofhansl <larsh@apache.org> | 2019-07-07 23:23:00 -0700 |
---|---|---|
committer | Lars Hofhansl <larsh@apache.org> | 2019-07-07 23:23:00 -0700 |
commit | 0971a14a57c373330b04d355689553f6ddfa6bcb (patch) | |
tree | 4cffac872c9a3456c30b9d988b90cdf6e75da9c1 /src | |
parent | 3a8ac9b03199cf0773107e58c69dd078892284a2 (diff) | |
download | minetest-0971a14a57c373330b04d355689553f6ddfa6bcb.tar.gz minetest-0971a14a57c373330b04d355689553f6ddfa6bcb.tar.bz2 minetest-0971a14a57c373330b04d355689553f6ddfa6bcb.zip |
Improve ABM time budget handling. #8645
Diffstat (limited to 'src')
-rw-r--r-- | src/serverenvironment.cpp | 87 | ||||
-rw-r--r-- | src/serverenvironment.h | 5 |
2 files changed, 54 insertions, 38 deletions
diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 0a83c4a38..3c4733130 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -384,6 +384,9 @@ void ActiveBlockList::update(std::vector<PlayerSAO*> &active_players, ServerEnvironment */ +// Random device to seed pseudo random generators. +static std::random_device seed; + ServerEnvironment::ServerEnvironment(ServerMap *map, ServerScripting *scriptIface, Server *server, const std::string &path_world): @@ -391,7 +394,8 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, m_map(map), m_script(scriptIface), m_server(server), - m_path_world(path_world) + m_path_world(path_world), + m_rgen(seed()) { // Determine which database backend to use std::string conf_path = path_world + DIR_DELIM + "world.mt"; @@ -1338,47 +1342,56 @@ void ServerEnvironment::step(float dtime) } } - if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval)) - do { // breakable - if (m_active_block_interval_overload_skip > 0) { - ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips"); - m_active_block_interval_overload_skip--; - break; - } - ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG); - TimeTaker timer("modify in active blocks per interval"); - - // Initialize handling of ActiveBlockModifiers - ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true); - - int blocks_scanned = 0; - int abms_run = 0; - int blocks_cached = 0; - for (const v3s16 &p : m_active_blocks.m_abm_list) { - MapBlock *block = m_map->getBlockNoCreateNoEx(p); - if (!block) - continue; + if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval)) { + ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG); + TimeTaker timer("modify in active blocks per interval"); - // Set current time as timestamp - block->setTimestampNoChangedFlag(m_game_time); + // Initialize handling of ActiveBlockModifiers + ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true); - /* Handle ActiveBlockModifiers */ - abmhandler.apply(block, blocks_scanned, abms_run, blocks_cached); - } - g_profiler->avg("SEnv: active blocks", m_active_blocks.m_abm_list.size()); - g_profiler->avg("SEnv: active blocks cached", blocks_cached); - g_profiler->avg("SEnv: active blocks scanned for ABMs", blocks_scanned); - g_profiler->avg("SEnv: ABMs run", abms_run); + int blocks_scanned = 0; + int abms_run = 0; + int blocks_cached = 0; + + std::vector<v3s16> output(m_active_blocks.m_abm_list.size()); + + // Shuffle the active blocks so that each block gets an equal chance + // of having its ABMs run. + std::copy(m_active_blocks.m_abm_list.begin(), m_active_blocks.m_abm_list.end(), output.begin()); + std::shuffle(output.begin(), output.end(), m_rgen); + + int i = 0; + // The time budget for ABMs is 20%. + u32 max_time_ms = m_cache_abm_interval * 1000 / 5; + for (const v3s16 &p : output) { + MapBlock *block = m_map->getBlockNoCreateNoEx(p); + if (!block) + continue; + + i++; + + // Set current time as timestamp + block->setTimestampNoChangedFlag(m_game_time); + + /* Handle ActiveBlockModifiers */ + abmhandler.apply(block, blocks_scanned, abms_run, blocks_cached); + + u32 time_ms = timer.getTimerTime(); - u32 time_ms = timer.stop(true); - u32 max_time_ms = 200; if (time_ms > max_time_ms) { - warningstream<<"active block modifiers took " - <<time_ms<<"ms (longer than " - <<max_time_ms<<"ms)"<<std::endl; - m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1; + warningstream << "active block modifiers took " + << time_ms << "ms (processed " << i << " of " + << output.size() << " active blocks)" << std::endl; + break; } - }while(0); + } + g_profiler->avg("SEnv: active blocks", m_active_blocks.m_abm_list.size()); + g_profiler->avg("SEnv: active blocks cached", blocks_cached); + g_profiler->avg("SEnv: active blocks scanned for ABMs", blocks_scanned); + g_profiler->avg("SEnv: ABMs run", abms_run); + + timer.stop(true); + } /* Step script environment (run global on_step()) diff --git a/src/serverenvironment.h b/src/serverenvironment.h index 77adcf627..cc4ecd797 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server/activeobjectmgr.h" #include "util/numeric.h" #include <set> +#include <random> class IGameDef; class ServerMap; @@ -446,7 +447,6 @@ private: IntervalLimiter m_active_blocks_management_interval; IntervalLimiter m_active_block_modifier_interval; IntervalLimiter m_active_blocks_nodemetadata_interval; - int m_active_block_interval_overload_skip = 0; // Time from the beginning of the game in seconds. // Incremented in step(). u32 m_game_time = 0; @@ -470,6 +470,9 @@ private: PlayerDatabase *m_player_database = nullptr; AuthDatabase *m_auth_database = nullptr; + // Pseudo random generator for shuffling, etc. + std::mt19937 m_rgen; + // Particles IntervalLimiter m_particle_management_interval; std::unordered_map<u32, float> m_particle_spawners; |