Add an active object step time budget #6721
This can be set via the active_object_interval option.master
parent
e049405fdc
commit
9c669016d1
|
@ -1085,6 +1085,9 @@ active_block_mgmt_interval (Active Block Management interval) float 2.0
|
||||||
# Length of time between ABM execution cycles
|
# Length of time between ABM execution cycles
|
||||||
abm_interval (Active Block Modifier interval) float 1.0
|
abm_interval (Active Block Modifier interval) float 1.0
|
||||||
|
|
||||||
|
# Length of time between active object step cycles
|
||||||
|
active_object_interval (Active Object interval) float 0.1
|
||||||
|
|
||||||
# Length of time between NodeTimer execution cycles
|
# Length of time between NodeTimer execution cycles
|
||||||
nodetimer_interval (NodeTimer interval) float 0.2
|
nodetimer_interval (NodeTimer interval) float 0.2
|
||||||
|
|
||||||
|
|
|
@ -345,6 +345,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("dedicated_server_step", "0.09");
|
settings->setDefault("dedicated_server_step", "0.09");
|
||||||
settings->setDefault("active_block_mgmt_interval", "2.0");
|
settings->setDefault("active_block_mgmt_interval", "2.0");
|
||||||
settings->setDefault("abm_interval", "1.0");
|
settings->setDefault("abm_interval", "1.0");
|
||||||
|
settings->setDefault("active_object_interval", "0.1");
|
||||||
settings->setDefault("nodetimer_interval", "0.2");
|
settings->setDefault("nodetimer_interval", "0.2");
|
||||||
settings->setDefault("ignore_world_load_errors", "false");
|
settings->setDefault("ignore_world_load_errors", "false");
|
||||||
settings->setDefault("remote_media", "");
|
settings->setDefault("remote_media", "");
|
||||||
|
|
|
@ -36,6 +36,7 @@ Environment::Environment(IGameDef *gamedef):
|
||||||
m_cache_enable_shaders = g_settings->getBool("enable_shaders");
|
m_cache_enable_shaders = g_settings->getBool("enable_shaders");
|
||||||
m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval");
|
m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval");
|
||||||
m_cache_abm_interval = g_settings->getFloat("abm_interval");
|
m_cache_abm_interval = g_settings->getFloat("abm_interval");
|
||||||
|
m_cache_ao_interval = g_settings->getFloat("active_object_interval");
|
||||||
m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval");
|
m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval");
|
||||||
|
|
||||||
m_time_of_day = g_settings->getU32("world_start_time");
|
m_time_of_day = g_settings->getU32("world_start_time");
|
||||||
|
|
|
@ -136,6 +136,7 @@ protected:
|
||||||
bool m_cache_enable_shaders;
|
bool m_cache_enable_shaders;
|
||||||
float m_cache_active_block_mgmt_interval;
|
float m_cache_active_block_mgmt_interval;
|
||||||
float m_cache_abm_interval;
|
float m_cache_abm_interval;
|
||||||
|
float m_cache_ao_interval;
|
||||||
float m_cache_nodetimer_interval;
|
float m_cache_nodetimer_interval;
|
||||||
|
|
||||||
IGameDef *m_gamedef;
|
IGameDef *m_gamedef;
|
||||||
|
|
|
@ -279,13 +279,13 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
|
||||||
|
|
||||||
void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
|
void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
|
||||||
{
|
{
|
||||||
|
const s16 r2 = r * r;
|
||||||
v3s16 p;
|
v3s16 p;
|
||||||
for (p.X = p0.X - r; p.X <= p0.X + r; p.X++)
|
for (p.X = p0.X - r; p.X <= p0.X + r; p.X++)
|
||||||
for (p.Y = p0.Y - r; p.Y <= p0.Y + r; p.Y++)
|
for (p.Y = p0.Y - r; p.Y <= p0.Y + r; p.Y++)
|
||||||
for(p.Z=p0.Z-r; p.Z<=p0.Z+r; p.Z++)
|
for (p.Z = p0.Z - r; p.Z <= p0.Z + r; p.Z++) {
|
||||||
{
|
|
||||||
// limit to a sphere
|
// limit to a sphere
|
||||||
if (p.getDistanceFrom(p0) <= r) {
|
if (p.getDistanceFromSQ(p0) <= r2) {
|
||||||
// Set in list
|
// Set in list
|
||||||
list.insert(p);
|
list.insert(p);
|
||||||
}
|
}
|
||||||
|
@ -364,10 +364,7 @@ void ActiveBlockList::update(std::vector<PlayerSAO*> &active_players,
|
||||||
/*
|
/*
|
||||||
Update m_list
|
Update m_list
|
||||||
*/
|
*/
|
||||||
m_list.clear();
|
m_list = newlist;
|
||||||
for (v3s16 p : newlist) {
|
|
||||||
m_list.insert(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1230,14 +1227,16 @@ void ServerEnvironment::step(float dtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// placeholder for the "real" time passed
|
||||||
|
float elapsed_time;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mess around in active blocks
|
Mess around in active blocks
|
||||||
*/
|
*/
|
||||||
if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval)) {
|
if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval,
|
||||||
|
&elapsed_time)) {
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG);
|
ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG);
|
||||||
|
|
||||||
float dtime = m_cache_nodetimer_interval;
|
|
||||||
|
|
||||||
for (const v3s16 &p: m_active_blocks.m_list) {
|
for (const v3s16 &p: m_active_blocks.m_list) {
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
if (!block)
|
if (!block)
|
||||||
|
@ -1255,7 +1254,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
MOD_REASON_BLOCK_EXPIRED);
|
MOD_REASON_BLOCK_EXPIRED);
|
||||||
|
|
||||||
// Run node timers
|
// Run node timers
|
||||||
std::vector<NodeTimer> elapsed_timers = block->m_node_timers.step(dtime);
|
std::vector<NodeTimer> elapsed_timers = block->m_node_timers.step(elapsed_time);
|
||||||
if (!elapsed_timers.empty()) {
|
if (!elapsed_timers.empty()) {
|
||||||
MapNode n;
|
MapNode n;
|
||||||
v3s16 p2;
|
v3s16 p2;
|
||||||
|
@ -1271,18 +1270,14 @@ 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 * m_active_block_interval_overload_skip, &elapsed_time))
|
||||||
do { // breakable
|
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");
|
||||||
|
|
||||||
// Initialize handling of ActiveBlockModifiers
|
// Initialize handling of ActiveBlockModifiers
|
||||||
ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true);
|
ABMHandler abmhandler(m_abms, elapsed_time, this, true);
|
||||||
|
|
||||||
for (const v3s16 &p : m_active_blocks.m_abm_list) {
|
for (const v3s16 &p : m_active_blocks.m_abm_list) {
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
|
@ -1296,13 +1291,16 @@ void ServerEnvironment::step(float dtime)
|
||||||
abmhandler.apply(block);
|
abmhandler.apply(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 time_ms = timer.stop(true);
|
const u32 time_ms = timer.stop(true);
|
||||||
u32 max_time_ms = 200;
|
// allow up to 10% of the budget interval
|
||||||
|
const u32 max_time_ms = m_cache_abm_interval * 1000.0f * 0.1f;
|
||||||
if (time_ms > max_time_ms) {
|
if (time_ms > max_time_ms) {
|
||||||
warningstream << "active block modifiers took "
|
warningstream << "active block modifiers took "
|
||||||
<< time_ms << "ms (longer than "
|
<< time_ms << "ms (longer than "
|
||||||
<< max_time_ms << "ms)" << std::endl;
|
<< max_time_ms << "ms)" << std::endl;
|
||||||
m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1;
|
m_active_block_interval_overload_skip = ((float)time_ms / max_time_ms);
|
||||||
|
} else {
|
||||||
|
m_active_block_interval_overload_skip = 1.0f;
|
||||||
}
|
}
|
||||||
}while(0);
|
}while(0);
|
||||||
|
|
||||||
|
@ -1314,15 +1312,17 @@ void ServerEnvironment::step(float dtime)
|
||||||
/*
|
/*
|
||||||
Step active objects
|
Step active objects
|
||||||
*/
|
*/
|
||||||
{
|
if (m_active_object_interval.step(dtime,
|
||||||
|
m_cache_ao_interval * m_active_object_interval_overload_skip, &elapsed_time)) {
|
||||||
|
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);
|
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);
|
||||||
//TimeTaker timer("Step active objects");
|
TimeTaker timer("Step active objects");
|
||||||
|
|
||||||
g_profiler->avg("SEnv: num of objects", m_active_objects.size());
|
g_profiler->avg("SEnv: num of objects", m_active_objects.size());
|
||||||
|
|
||||||
// This helps the objects to send data at the same time
|
// This helps the objects to send data at the same time
|
||||||
bool send_recommended = false;
|
bool send_recommended = false;
|
||||||
m_send_recommended_timer += dtime;
|
m_send_recommended_timer += elapsed_time;
|
||||||
if(m_send_recommended_timer > getSendRecommendedInterval())
|
if(m_send_recommended_timer > getSendRecommendedInterval())
|
||||||
{
|
{
|
||||||
m_send_recommended_timer -= getSendRecommendedInterval();
|
m_send_recommended_timer -= getSendRecommendedInterval();
|
||||||
|
@ -1335,13 +1335,28 @@ void ServerEnvironment::step(float dtime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Step object
|
// Step object
|
||||||
obj->step(dtime, send_recommended);
|
obj->step(elapsed_time, send_recommended);
|
||||||
// Read messages from object
|
// Read messages from object
|
||||||
while (!obj->m_messages_out.empty()) {
|
while (!obj->m_messages_out.empty()) {
|
||||||
m_active_object_messages.push(obj->m_messages_out.front());
|
m_active_object_messages.push(obj->m_messages_out.front());
|
||||||
obj->m_messages_out.pop();
|
obj->m_messages_out.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate a simple moving average
|
||||||
|
m_avg_ao_time = m_avg_ao_time * 0.9f + timer.stop(true) * 0.1f;
|
||||||
|
|
||||||
|
// allow up to 20% of the budget interval
|
||||||
|
const float max_time_ms = m_cache_ao_interval * 1000.0f * 0.2f;
|
||||||
|
if (m_avg_ao_time > max_time_ms) {
|
||||||
|
warningstream << "active objects took "
|
||||||
|
<< m_avg_ao_time << "ms (longer than "
|
||||||
|
<< max_time_ms << "ms)" << std::endl;
|
||||||
|
// skip a few steps
|
||||||
|
m_active_object_interval_overload_skip = m_avg_ao_time / max_time_ms;
|
||||||
|
} else {
|
||||||
|
m_active_object_interval_overload_skip = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -422,8 +422,11 @@ private:
|
||||||
ActiveBlockList m_active_blocks;
|
ActiveBlockList m_active_blocks;
|
||||||
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_object_interval;
|
||||||
IntervalLimiter m_active_blocks_nodemetadata_interval;
|
IntervalLimiter m_active_blocks_nodemetadata_interval;
|
||||||
int m_active_block_interval_overload_skip = 0;
|
float m_active_block_interval_overload_skip = 1.0f;
|
||||||
|
float m_active_object_interval_overload_skip = 1.0f;
|
||||||
|
float m_avg_ao_time = 0.0f;
|
||||||
// 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;
|
||||||
|
|
|
@ -291,18 +291,24 @@ public:
|
||||||
return value:
|
return value:
|
||||||
true: action should be skipped
|
true: action should be skipped
|
||||||
false: action should be done
|
false: action should be done
|
||||||
|
if passed, the elapsed time since this method last returned true
|
||||||
|
is written to elapsed_ptr
|
||||||
*/
|
*/
|
||||||
bool step(float dtime, float wanted_interval)
|
bool step(float dtime, float wanted_interval, float *elapsed_ptr = NULL)
|
||||||
{
|
{
|
||||||
m_accumulator += dtime;
|
m_accumulator += dtime;
|
||||||
|
if (elapsed_ptr)
|
||||||
|
*elapsed_ptr = m_accumulator - m_last_accumulator;
|
||||||
if (m_accumulator < wanted_interval)
|
if (m_accumulator < wanted_interval)
|
||||||
return false;
|
return false;
|
||||||
m_accumulator -= wanted_interval;
|
m_accumulator -= wanted_interval;
|
||||||
|
m_last_accumulator = m_accumulator;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_accumulator = 0.0f;
|
float m_accumulator = 0.0f;
|
||||||
|
float m_last_accumulator = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue