From 0ea47fadeedeadbd1535259cda5eae6f5d0e06cb Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Fri, 8 Nov 2024 17:48:39 -0600 Subject: [PATCH] [Performance] Improvements to ScanCloseMobs logic (#4534) * [Performance] Minor improvements to ScanCloseMobs * Remove timer checks one level up to reduce branching * Reserve memory in m_close_mobs to avoid frequent re-allocations if not already reserved. --- zone/bot.cpp | 5 ++++- zone/client_packet.cpp | 6 +++++- zone/client_process.cpp | 4 +++- zone/entity.cpp | 30 +++++++++++------------------- zone/mob.cpp | 34 ++++++++++++---------------------- zone/mob.h | 1 - zone/npc.cpp | 9 +++++++-- 7 files changed, 42 insertions(+), 47 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ce7edcc82..7871f9ac9 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1578,7 +1578,10 @@ bool Bot::Process() return false; } - ScanCloseMobProcess(); + if (m_scan_close_mobs_timer.Check()) { + entity_list.ScanCloseMobs(this); + } + SpellProcess(); if (tic_timer.Check()) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c880e310f..83af9b13d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5013,7 +5013,11 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { SetMoving(!(cy == m_Position.y && cx == m_Position.x)); CheckClientToNpcAggroTimer(); - CheckScanCloseMobsMovingTimer(); + + if (m_mob_check_moving_timer.Check()) { + CheckScanCloseMobsMovingTimer(); + } + CheckSendBulkClientPositionUpdate(); int32 new_animation = ppu->animation; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index d0dab4c27..c2e20fe5b 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -281,7 +281,9 @@ bool Client::Process() { } } - ScanCloseMobProcess(); + if (m_scan_close_mobs_timer.Check()) { + entity_list.ScanCloseMobs(this); + } if (RuleB(Inventory, LazyLoadBank)) { // poll once a second to see if we are close to a banker and we haven't loaded the bank yet diff --git a/zone/entity.cpp b/zone/entity.cpp index c21856d37..d4b3ff72f 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2947,6 +2947,12 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob) { float scan_range = RuleI(Range, MobCloseScanDistance) * RuleI(Range, MobCloseScanDistance); + // Reserve memory in m_close_mobs to avoid frequent re-allocations if not already reserved. + // Assuming mob_list.size() as an upper bound for reservation. + if (scanning_mob->m_close_mobs.bucket_count() < mob_list.size()) { + scanning_mob->m_close_mobs.reserve(mob_list.size()); + } + scanning_mob->m_close_mobs.clear(); for (auto &e : mob_list) { @@ -2957,28 +2963,14 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob) float distance = DistanceSquared(scanning_mob->GetPosition(), mob->GetPosition()); if (distance <= scan_range || mob->GetAggroRange() >= scan_range) { - scanning_mob->m_close_mobs.emplace(std::pair(mob->GetID(), mob)); - - // add self to other mobs close list - if (scanning_mob->GetID() > 0) { - bool has_mob = false; - - for (auto &cm: mob->m_close_mobs) { - if (scanning_mob->GetID() == cm.first) { - has_mob = true; - break; - } - } - - if (!has_mob) { - mob->m_close_mobs.insert(std::pair(scanning_mob->GetID(), scanning_mob)); - } - } + // add mob to scanning_mob's close list and vice versa + mob->m_close_mobs[scanning_mob->GetID()] = scanning_mob; + scanning_mob->m_close_mobs[mob->GetID()] = mob; } } - LogAIScanCloseDetail( - "[{}] Scanning Close List | list_size [{}] moving [{}]", + LogAIScanClose( + "[{}] Scanning close list > list_size [{}] moving [{}]", scanning_mob->GetCleanName(), scanning_mob->m_close_mobs.size(), scanning_mob->IsMoving() ? "true" : "false" diff --git a/zone/mob.cpp b/zone/mob.cpp index a1d9b5d38..2b43ff5e2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -8584,6 +8584,7 @@ bool Mob::HasBotAttackFlag(Mob* tar) { const uint16 scan_close_mobs_timer_moving = 6000; // 6 seconds const uint16 scan_close_mobs_timer_idle = 60000; // 60 seconds +// If the moving timer triggers, lets see if we are moving or idle to restart the appropriate dynamic timer void Mob::CheckScanCloseMobsMovingTimer() { LogAIScanCloseDetail( @@ -8593,31 +8594,20 @@ void Mob::CheckScanCloseMobsMovingTimer() m_scan_close_mobs_timer.GetRemainingTime() ); - // If the moving timer triggers, lets see if we are moving or idle to restart the appropriate - // dynamic timer - if (m_mob_check_moving_timer.Check()) { - // If the mob is still moving, restart the moving timer - if (moving) { - if (m_scan_close_mobs_timer.GetRemainingTime() > scan_close_mobs_timer_moving) { - LogAIScanCloseDetail("Mob [{}] Restarting with moving timer", GetCleanName()); - m_scan_close_mobs_timer.Disable(); - m_scan_close_mobs_timer.Start(scan_close_mobs_timer_moving); - m_scan_close_mobs_timer.Trigger(); - } - } - // If the mob is not moving, restart the idle timer - else if (m_scan_close_mobs_timer.GetDuration() == scan_close_mobs_timer_moving) { - LogAIScanCloseDetail("Mob [{}] Restarting with idle timer", GetCleanName()); + // If the mob is still moving, restart the moving timer + if (moving) { + if (m_scan_close_mobs_timer.GetRemainingTime() > scan_close_mobs_timer_moving) { + LogAIScanCloseDetail("Mob [{}] Restarting with moving timer", GetCleanName()); m_scan_close_mobs_timer.Disable(); - m_scan_close_mobs_timer.Start(scan_close_mobs_timer_idle); + m_scan_close_mobs_timer.Start(scan_close_mobs_timer_moving); + m_scan_close_mobs_timer.Trigger(); } } -} - -void Mob::ScanCloseMobProcess() -{ - if (m_scan_close_mobs_timer.Check()) { - entity_list.ScanCloseMobs(this); + // If the mob is not moving, restart the idle timer + else if (m_scan_close_mobs_timer.GetDuration() == scan_close_mobs_timer_moving) { + LogAIScanCloseDetail("Mob [{}] Restarting with idle timer", GetCleanName()); + m_scan_close_mobs_timer.Disable(); + m_scan_close_mobs_timer.Start(scan_close_mobs_timer_idle); } } diff --git a/zone/mob.h b/zone/mob.h index 8914534cb..d1bf386d6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1488,7 +1488,6 @@ public: bool IsCloseToBanker(); - void ScanCloseMobProcess(); std::unordered_map &GetCloseMobList(float distance = 0.0f); void CheckScanCloseMobsMovingTimer(); diff --git a/zone/npc.cpp b/zone/npc.cpp index 2172a529e..f65bd7fad 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -601,8 +601,13 @@ bool NPC::Process() DepopSwarmPets(); } - ScanCloseMobProcess(); - CheckScanCloseMobsMovingTimer(); + if (m_scan_close_mobs_timer.Check()) { + entity_list.ScanCloseMobs(this); + } + + if (m_mob_check_moving_timer.Check()) { + CheckScanCloseMobsMovingTimer(); + } if (hp_regen_per_second > 0 && hp_regen_per_second_timer.Check()) { if (GetHP() < GetMaxHP()) {