Skip to content
Permalink
Browse files

Improve ABM time budget handling. #8645

  • Loading branch information...
lhofhansl committed Jul 8, 2019
1 parent 3a8ac9b commit 0971a14a57c373330b04d355689553f6ddfa6bcb
Showing with 54 additions and 38 deletions.
  1. +50 −37 src/serverenvironment.cpp
  2. +4 −1 src/serverenvironment.h
@@ -384,14 +384,18 @@ 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):
Environment(server),
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())
@@ -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 @@ class ServerEnvironment : public Environment
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 @@ class ServerEnvironment : public Environment
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;

0 comments on commit 0971a14

Please sign in to comment.
You can’t perform that action at this time.