9.4 KiB
Phase 2D Analysis: BotThreatManager.cpp ObjectAccessor Migration
File: src/modules/Playerbot/AI/Combat/BotThreatManager.cpp
Total ObjectAccessor Calls: 14
Priority: HIGH (hot path, high-frequency updates)
Current Optimization State: Partially optimized with "PHASE 5B" patterns
Complexity: Medium
Executive Summary
BotThreatManager.cpp contains 14 ObjectAccessor calls, making it the second-highest usage file in Phase 2D. However, analysis reveals the file is already partially optimized with snapshot validation patterns labeled "PHASE 5B".
Key Findings:
- Already optimized: 10/14 calls use snapshot validation first (good pattern)
- Necessary calls: Most remaining calls require Unit* for TrinityCore APIs
- Optimization opportunities: 2-3 redundant alive checks can be eliminated
- Expected reduction: 14 → 12-13 calls (14-21% reduction, not 85% as roadmap estimated)
Recommendation: Minor cleanup only - file is already well-optimized.
Detailed Call Analysis
Category 1: Already Optimized (10 calls)
These calls already use the snapshot-first pattern:
// PHASE 5B pattern: Validate with snapshot first
auto snapshot = SpatialGridQueryHelpers::FindCreatureByGuid(_bot, guid);
if (!snapshot || !snapshot->IsAlive())
continue;
// ONLY get Unit* when snapshot confirms alive
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
Locations:
- Line 287:
AnalyzeThreatSituation()- Need Unit* for threat calculations - Line 409:
RecalculateThreatPriorities()- Need Unit* for ThreatCalculator - Line 463:
RecalculateThreatPriorities()(healer check) - Need Unit* for GetVictim() - Line 554:
GetAllThreatTargets()- RETURN TYPE: std::vector<Unit>* - Line 579:
GetThreatTargetsByPriority()- RETURN TYPE: std::vector<Unit>* - Line 841:
UpdateThreatInfo()- Need Unit* for GetThreatManager()
Analysis: These are necessary and already optimized. The functions that return std::vector<Unit*> MUST call ObjectAccessor because callers expect Unit* pointers.
Category 2: Helper Function (1 call)
ThreatTarget::GetUnit() - Line 33
Unit* ThreatTarget::GetUnit(Player* bot) const
{
if (!bot || targetGuid.IsEmpty())
return nullptr;
return ObjectAccessor::GetUnit(*bot, targetGuid);
}
Analysis: This is a helper function for legacy API compatibility. Used by external callers who need Unit*.
Optimization Potential: CANNOT OPTIMIZE - Return type is Unit*, required by API contract.
Category 3: Iteration Helpers (2 calls)
CleanupInvalidThreats() - Line 881
for (auto& [guid, info] : _threatMap)
{
// PHASE 5B: Thread-safe spatial grid query (replaces ObjectAccessor::GetUnit)
auto snapshot = SpatialGridQueryHelpers::FindCreatureByGuid(_bot, guid);
if (!snapshot)
continue;
// ... mark as inactive
}
UpdateThreatDistances() - Line 896
for (auto& [guid, info] : _threatMap)
{
// PHASE 5B: Thread-safe spatial grid query (replaces ObjectAccessor::GetUnit)
auto snapshot = SpatialGridQueryHelpers::FindCreatureByGuid(_bot, guid);
if (!snapshot)
continue;
// ... update distance from snapshot->position
}
Analysis: These functions do NOT call ObjectAccessor - they use snapshot-only validation. Already fully optimized.
Optimization Opportunities
Opportunity 1: Remove Redundant IsAlive() Checks
Issue: Functions validate with snapshot->IsAlive(), then call ObjectAccessor, then check target->IsAlive() AGAIN.
Affected Functions:
GetAllThreatTargets()- Line 554-555GetThreatTargetsByPriority()- Line 579-580
Current Pattern (REDUNDANT):
// Validate with snapshot
auto snapshot = SpatialGridQueryHelpers::FindCreatureByGuid(_bot, guid);
if (!snapshot || !snapshot->IsAlive()) // CHECK #1
continue;
// Get Unit*
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
if (target && target->IsAlive()) // CHECK #2 - REDUNDANT!
targets.push_back(target);
Optimized Pattern:
// Validate with snapshot
auto snapshot = SpatialGridQueryHelpers::FindCreatureByGuid(_bot, guid);
if (!snapshot || !snapshot->IsAlive())
continue;
// Snapshot confirms alive, just get Unit*
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
if (target) // Only null check needed
targets.push_back(target);
Impact: Eliminates 2 redundant IsAlive() calls per target in returned vectors.
Opportunity 2: NONE - Return Type Constraints
The following functions CANNOT be optimized further because they return std::vector<Unit*>:
GetAllThreatTargets()- Callers expect Unit* pointersGetThreatTargetsByPriority()- Callers expect Unit* pointersThreatTarget::GetUnit()- Return type is Unit*
These functions MUST call ObjectAccessor to satisfy API contract with callers.
Opportunity 3: Update Phase Labels
Issue: File has inconsistent phase labels:
- Line 27: "PHASE 2B" comment
- Lines 276, 403, 457, 548, 573, 880, 895: "PHASE 5B" comments
Recommendation: Update all comments to "PHASE 2D" for consistency with current work.
Expected Results
Call Reduction Summary
| Category | Before | After | Reduction | Notes |
|---|---|---|---|---|
| Already optimized (necessary) | 10 | 10 | 0% | Required for TrinityCore APIs |
| Helper function | 1 | 1 | 0% | API contract |
| Iteration helpers | 0 | 0 | N/A | Already snapshot-only |
| Redundant checks (cleanup) | 2 | 0 | 100% | Remove redundant IsAlive() |
| TOTAL | 14 | 12-13 | 14-21% | vs. 85% roadmap estimate |
Performance Impact
Current State:
- BotThreatManager update frequency: ~10-20 Hz during combat
- ObjectAccessor calls: 14 per update × 15 Hz = 210 calls/sec
After Optimization:
- ObjectAccessor calls: 13 per update × 15 Hz = 195 calls/sec
- Reduction: 15 calls/sec eliminated (7%)
FPS Impact (100 bot scenario):
- Estimated improvement: <1% FPS gain (minimal, file already optimized)
Roadmap Discrepancy Analysis
Roadmap Estimate vs. Reality
Roadmap Projection (PHASE2_NEXT_STEPS_ROADMAP.md):
- Estimated reduction: 10-12 calls (85%)
- Expected impact: Part of 8-12% Phase 2D FPS gain
Actual Finding:
- Realistic reduction: 1-2 calls (14-21%)
- Expected impact: <1% FPS gain
Root Cause: Roadmap did not account for "PHASE 5B" optimizations already present in the file.
Detailed Migration Plan
Step 1: Remove Redundant IsAlive() Checks
GetAllThreatTargets() - Lines 553-556
BEFORE:
// Get actual Unit* for return vector (needed by callers)
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
if (target && target->IsAlive())
targets.push_back(target);
AFTER:
// PHASE 2D: Snapshot already validated IsAlive(), only null check needed
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
if (target)
targets.push_back(target);
GetThreatTargetsByPriority() - Lines 578-581
BEFORE:
// Get actual Unit* for return vector (needed by callers)
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
if (target && target->IsAlive())
targets.push_back(target);
AFTER:
// PHASE 2D: Snapshot already validated IsAlive(), only null check needed
Unit* target = ObjectAccessor::GetUnit(*_bot, guid);
if (target)
targets.push_back(target);
Step 2: Update Phase Labels (Optional)
Replace all "PHASE 5B" comments with "PHASE 2D" for consistency:
Affected Lines: 276, 403, 457, 548, 573, 880, 895
Example:
// BEFORE:
// PHASE 5B: Thread-safe spatial grid validation (replaces ObjectAccessor::GetUnit)
// AFTER:
// PHASE 2D: Thread-safe spatial grid validation (replaces ObjectAccessor::GetUnit)
Conclusion
BotThreatManager.cpp is already well-optimized with snapshot-first patterns. The roadmap estimate of 85% reduction was based on the assumption that the file had not been optimized, but it already contains "PHASE 5B" optimizations.
Key Findings:
- 10/14 ObjectAccessor calls are necessary - require Unit* for TrinityCore APIs
- 2/14 calls can be slightly optimized - remove redundant IsAlive() checks
- 2/14 calls are already snapshot-only - no ObjectAccessor called
- Expected reduction: 14 → 12-13 calls (14-21%, not 85%)
Recommendation:
Option A: Minor Cleanup (Recommended)
- Remove 2 redundant IsAlive() checks
- Update phase labels to "PHASE 2D"
- Effort: 15 minutes
- Impact: <1% FPS gain, improved code clarity
Option B: Skip This File
- File is already well-optimized
- Focus effort on higher-impact files (GroupCombatTrigger, TargetSelector, etc.)
- Effort: 0 minutes
- Impact: Same performance (file already optimized)
Recommended Action: Option A - quick cleanup for completeness, then move to next file.
Next File Recommendation
Based on roadmap priority and actual optimization potential:
- GroupCombatTrigger.cpp (5 calls) - Combat initiation, group coordination
- TargetSelector.cpp (4 calls) - Target selection, distance calculations
- TargetScanner.cpp (3 calls) - Enemy scanning, proximity checks
- LineOfSightManager.cpp (3 calls) - LOS validation (LOSCache integration)
- InterruptAwareness.cpp (3 calls) - Interrupt target validation
These files likely have higher optimization potential than BotThreatManager.cpp.
End of Analysis