forked from Mirrorlandia_minetest/minetest
Improve ABM time budget handling. #8645
This commit is contained in:
parent
3a8ac9b031
commit
0971a14a57
@ -384,6 +384,9 @@ void ActiveBlockList::update(std::vector<PlayerSAO*> &active_players,
|
|||||||
ServerEnvironment
|
ServerEnvironment
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Random device to seed pseudo random generators.
|
||||||
|
static std::random_device seed;
|
||||||
|
|
||||||
ServerEnvironment::ServerEnvironment(ServerMap *map,
|
ServerEnvironment::ServerEnvironment(ServerMap *map,
|
||||||
ServerScripting *scriptIface, Server *server,
|
ServerScripting *scriptIface, Server *server,
|
||||||
const std::string &path_world):
|
const std::string &path_world):
|
||||||
@ -391,7 +394,8 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
|
|||||||
m_map(map),
|
m_map(map),
|
||||||
m_script(scriptIface),
|
m_script(scriptIface),
|
||||||
m_server(server),
|
m_server(server),
|
||||||
m_path_world(path_world)
|
m_path_world(path_world),
|
||||||
|
m_rgen(seed())
|
||||||
{
|
{
|
||||||
// Determine which database backend to use
|
// Determine which database backend to use
|
||||||
std::string conf_path = path_world + DIR_DELIM + "world.mt";
|
std::string conf_path = path_world + DIR_DELIM + "world.mt";
|
||||||
@ -1338,13 +1342,7 @@ void ServerEnvironment::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval))
|
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);
|
ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG);
|
||||||
TimeTaker timer("modify in active blocks per interval");
|
TimeTaker timer("modify in active blocks per interval");
|
||||||
|
|
||||||
@ -1354,31 +1352,46 @@ void ServerEnvironment::step(float dtime)
|
|||||||
int blocks_scanned = 0;
|
int blocks_scanned = 0;
|
||||||
int abms_run = 0;
|
int abms_run = 0;
|
||||||
int blocks_cached = 0;
|
int blocks_cached = 0;
|
||||||
for (const v3s16 &p : m_active_blocks.m_abm_list) {
|
|
||||||
|
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);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
if (!block)
|
if (!block)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
// Set current time as timestamp
|
// Set current time as timestamp
|
||||||
block->setTimestampNoChangedFlag(m_game_time);
|
block->setTimestampNoChangedFlag(m_game_time);
|
||||||
|
|
||||||
/* Handle ActiveBlockModifiers */
|
/* Handle ActiveBlockModifiers */
|
||||||
abmhandler.apply(block, blocks_scanned, abms_run, blocks_cached);
|
abmhandler.apply(block, blocks_scanned, abms_run, blocks_cached);
|
||||||
|
|
||||||
|
u32 time_ms = timer.getTimerTime();
|
||||||
|
|
||||||
|
if (time_ms > max_time_ms) {
|
||||||
|
warningstream << "active block modifiers took "
|
||||||
|
<< time_ms << "ms (processed " << i << " of "
|
||||||
|
<< output.size() << " active blocks)" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_profiler->avg("SEnv: active blocks", m_active_blocks.m_abm_list.size());
|
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 cached", blocks_cached);
|
||||||
g_profiler->avg("SEnv: active blocks scanned for ABMs", blocks_scanned);
|
g_profiler->avg("SEnv: active blocks scanned for ABMs", blocks_scanned);
|
||||||
g_profiler->avg("SEnv: ABMs run", abms_run);
|
g_profiler->avg("SEnv: ABMs run", abms_run);
|
||||||
|
|
||||||
u32 time_ms = timer.stop(true);
|
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;
|
|
||||||
}
|
}
|
||||||
}while(0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Step script environment (run global on_step())
|
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 "server/activeobjectmgr.h"
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
class ServerMap;
|
class ServerMap;
|
||||||
@ -446,7 +447,6 @@ private:
|
|||||||
IntervalLimiter m_active_blocks_management_interval;
|
IntervalLimiter m_active_blocks_management_interval;
|
||||||
IntervalLimiter m_active_block_modifier_interval;
|
IntervalLimiter m_active_block_modifier_interval;
|
||||||
IntervalLimiter m_active_blocks_nodemetadata_interval;
|
IntervalLimiter m_active_blocks_nodemetadata_interval;
|
||||||
int m_active_block_interval_overload_skip = 0;
|
|
||||||
// Time from the beginning of the game in seconds.
|
// Time from the beginning of the game in seconds.
|
||||||
// Incremented in step().
|
// Incremented in step().
|
||||||
u32 m_game_time = 0;
|
u32 m_game_time = 0;
|
||||||
@ -470,6 +470,9 @@ private:
|
|||||||
PlayerDatabase *m_player_database = nullptr;
|
PlayerDatabase *m_player_database = nullptr;
|
||||||
AuthDatabase *m_auth_database = nullptr;
|
AuthDatabase *m_auth_database = nullptr;
|
||||||
|
|
||||||
|
// Pseudo random generator for shuffling, etc.
|
||||||
|
std::mt19937 m_rgen;
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
IntervalLimiter m_particle_management_interval;
|
IntervalLimiter m_particle_management_interval;
|
||||||
std::unordered_map<u32, float> m_particle_spawners;
|
std::unordered_map<u32, float> m_particle_spawners;
|
||||||
|
Loading…
Reference in New Issue
Block a user