forked from Mirrorlandia_minetest/minetest
Optimize ABM checks.
See #7555 Cache (up to 64) node types for each active block. Check this cache first to see whether any ABM needs to be triggered for a block.
This commit is contained in:
parent
c022ddce4b
commit
25cc5d1a32
@ -114,6 +114,8 @@ public:
|
|||||||
} else if (mod == m_modified) {
|
} else if (mod == m_modified) {
|
||||||
m_modified_reason |= reason;
|
m_modified_reason |= reason;
|
||||||
}
|
}
|
||||||
|
if (mod == MOD_STATE_WRITE_NEEDED)
|
||||||
|
contents_cached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 getModified()
|
inline u32 getModified()
|
||||||
@ -529,6 +531,14 @@ public:
|
|||||||
|
|
||||||
static const u32 nodecount = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
static const u32 nodecount = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
||||||
|
|
||||||
|
//// ABM optimizations ////
|
||||||
|
// Cache of content types
|
||||||
|
std::unordered_set<content_t> contents;
|
||||||
|
// True if content types are cached
|
||||||
|
bool contents_cached = false;
|
||||||
|
// True if we never want to cache content types for this block
|
||||||
|
bool do_not_cache_contents = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
Private member variables
|
Private member variables
|
||||||
|
@ -800,11 +800,31 @@ public:
|
|||||||
return active_object_count;
|
return active_object_count;
|
||||||
|
|
||||||
}
|
}
|
||||||
void apply(MapBlock *block)
|
void apply(MapBlock *block, int &blocks_scanned, int &abms_run, int &blocks_cached)
|
||||||
{
|
{
|
||||||
if(m_aabms.empty() || block->isDummy())
|
if(m_aabms.empty() || block->isDummy())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Check the content type cache first
|
||||||
|
// to see whether there are any ABMs
|
||||||
|
// to be run at all for this block.
|
||||||
|
if (block->contents_cached) {
|
||||||
|
blocks_cached++;
|
||||||
|
bool run_abms = false;
|
||||||
|
for (content_t c : block->contents) {
|
||||||
|
if (c < m_aabms.size() && m_aabms[c]) {
|
||||||
|
run_abms = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!run_abms)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Clear any caching
|
||||||
|
block->contents.clear();
|
||||||
|
}
|
||||||
|
blocks_scanned++;
|
||||||
|
|
||||||
ServerMap *map = &m_env->getServerMap();
|
ServerMap *map = &m_env->getServerMap();
|
||||||
|
|
||||||
u32 active_object_count_wider;
|
u32 active_object_count_wider;
|
||||||
@ -818,6 +838,15 @@ public:
|
|||||||
{
|
{
|
||||||
const MapNode &n = block->getNodeUnsafe(p0);
|
const MapNode &n = block->getNodeUnsafe(p0);
|
||||||
content_t c = n.getContent();
|
content_t c = n.getContent();
|
||||||
|
// Cache content types as we go
|
||||||
|
if (!block->contents_cached && !block->do_not_cache_contents) {
|
||||||
|
block->contents.insert(c);
|
||||||
|
if (block->contents.size() > 64) {
|
||||||
|
// Too many different nodes... don't try to cache
|
||||||
|
block->do_not_cache_contents = true;
|
||||||
|
block->contents.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (c >= m_aabms.size() || !m_aabms[c])
|
if (c >= m_aabms.size() || !m_aabms[c])
|
||||||
continue;
|
continue;
|
||||||
@ -855,6 +884,7 @@ public:
|
|||||||
}
|
}
|
||||||
neighbor_found:
|
neighbor_found:
|
||||||
|
|
||||||
|
abms_run++;
|
||||||
// Call all the trigger variations
|
// Call all the trigger variations
|
||||||
aabm.abm->trigger(m_env, p, n);
|
aabm.abm->trigger(m_env, p, n);
|
||||||
aabm.abm->trigger(m_env, p, n,
|
aabm.abm->trigger(m_env, p, n,
|
||||||
@ -867,6 +897,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
block->contents_cached = !block->do_not_cache_contents;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1302,6 +1333,9 @@ void ServerEnvironment::step(float dtime)
|
|||||||
// Initialize handling of ActiveBlockModifiers
|
// Initialize handling of ActiveBlockModifiers
|
||||||
ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true);
|
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) {
|
for (const v3s16 &p : m_active_blocks.m_abm_list) {
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
if (!block)
|
if (!block)
|
||||||
@ -1311,8 +1345,12 @@ void ServerEnvironment::step(float dtime)
|
|||||||
block->setTimestampNoChangedFlag(m_game_time);
|
block->setTimestampNoChangedFlag(m_game_time);
|
||||||
|
|
||||||
/* Handle ActiveBlockModifiers */
|
/* Handle ActiveBlockModifiers */
|
||||||
abmhandler.apply(block);
|
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);
|
||||||
|
|
||||||
u32 time_ms = timer.stop(true);
|
u32 time_ms = timer.stop(true);
|
||||||
u32 max_time_ms = 200;
|
u32 max_time_ms = 200;
|
||||||
|
Loading…
Reference in New Issue
Block a user