perf(mmap): Cache failed MMAP load attempts to prevent repeated retries

Similar to the VMAP fix, this caches failed MMAP load attempts using a
bitset per TerrainInfo instance. This prevents the server from repeatedly
attempting to load MMAP tiles that don't exist (e.g., unused dungeon maps,
boost experience maps, etc.), which was causing significant slowdowns.

Changes:
- Add _mmapLoadFailed bitset to TerrainInfo class
- Skip LoadMMapImpl early if grid already marked as failed
- Cache FileNotFound, VersionMismatch, ReadFromFileFailed, and
  LibraryError results
- Change expected "FileNotFound" log level from WARN to DEBUG
- Update analysis documentation with fix status

Impact: Near-instant returns for grids with missing MMAP data instead of
repeated file I/O attempts.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
This commit is contained in:
agatho
2026-02-02 13:31:23 -03:00
committed by luis
co-authored by Claude Opus 4.5
parent cfe60008d5
commit c986da9c77
3 changed files with 40 additions and 2 deletions
@@ -353,13 +353,36 @@ When 100 bots enter a map simultaneously, ALL 100 queue on exclusive lock.
| GameSystemsManager Throttling | HIGH | ✅ FIXED | ~30x fewer manager updates |
| SpatialGridManager Thundering Herd | MEDIUM | ✅ FIXED | Instant returns for existing grids |
| Main Thread ThreadPool Blocking | HIGH | ⚠️ MITIGATED | Fixed by making workers faster |
| CombatEventRouter | MEDIUM | ⏳ ACCEPTABLE | Already uses good patterns |
| CombatEventRouter | MEDIUM | ✅ FIXED | Lock-free stats with atomics |
| VMAP Repeated Load Attempts | HIGH | ✅ FIXED | Cache failed loads, no retries |
| MMAP Repeated Load Attempts | HIGH | ✅ FIXED | Cache failed loads, no retries |
| Unordered Mutexes | LOW | ⏳ DEFERRED | For future cleanup |
**Total Build Status:** ✅ worldserver.exe compiled successfully
---
## VMAP/MMAP LOAD CACHING FIX
### Problem
When maps reference VMAP/MMAP tiles that don't exist in client data (e.g., "8.0 Boost Experience",
TWW dungeons), the server repeatedly attempts to load them on every grid access, causing:
- Repeated file I/O operations
- Log spam with warnings
- Significant server slowdown
### Solution
Added `_vmapLoadFailed` and `_mmapLoadFailed` bitset caches to `TerrainInfo` class:
- On first load failure, mark the grid as failed
- Skip subsequent load attempts for the same grid
- Changed log level from WARN to DEBUG for expected failures
**File:** `src/server/game/Maps/TerrainMgr.h` and `TerrainMgr.cpp`
**Expected Impact:** Near-instant returns for grids with missing map data
---
## THREADING CONFIGURATION
### TrinityCore MapUpdate.Threads
+15 -1
View File
@@ -252,6 +252,10 @@ void TerrainInfo::LoadMMapImpl(uint32 instanceId, int32 gx, int32 gy)
if (!DisableMgr::IsPathfindingEnabled(GetId()))
return;
// PLAYERBOT FIX: Skip loading if we already know this tile failed (prevents repeated file access attempts)
if (_mmapLoadFailed[GetBitsetIndex(gx, gy)])
return;
switch (MMAP::LoadResult mmapLoadResult = MMAP::MMapManager::instance()->loadMap(sWorld->GetDataPath(), GetId(), instanceId, gx, gy))
{
case MMAP::LoadResult::Success:
@@ -260,9 +264,19 @@ void TerrainInfo::LoadMMapImpl(uint32 instanceId, int32 gx, int32 gy)
case MMAP::LoadResult::AlreadyLoaded:
break;
case MMAP::LoadResult::FileNotFound:
// PLAYERBOT FIX: Cache the failure to prevent repeated load attempts
_mmapLoadFailed[GetBitsetIndex(gx, gy)] = true;
if (_parentTerrain)
break; // don't log tile not found errors for child maps
[[fallthrough]];
TC_LOG_DEBUG("mmaps.tiles", "MMAP not available name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{}) - will not retry", GetMapName(), GetId(), gx, gy, gx, gy);
break;
case MMAP::LoadResult::VersionMismatch:
case MMAP::LoadResult::ReadFromFileFailed:
case MMAP::LoadResult::LibraryError:
// PLAYERBOT FIX: Cache these failures too - they won't succeed on retry
_mmapLoadFailed[GetBitsetIndex(gx, gy)] = true;
TC_LOG_WARN("mmaps.tiles", "MMAP failed name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{}) result: {} - will not retry", GetMapName(), GetId(), gx, gy, gx, gy, AsUnderlyingType(mmapLoadResult));
break;
default:
TC_LOG_WARN("mmaps.tiles", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{}) result: {}", GetMapName(), GetId(), gx, gy, gx, gy, AsUnderlyingType(mmapLoadResult));
break;
+1
View File
@@ -116,6 +116,7 @@ private:
std::array<uint64, MAX_NUMBER_OF_GRIDS> _loadedGrids;
std::bitset<MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS> _gridFileExists; // cache what grids are available for this map (not including parent/child maps)
std::bitset<MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS> _vmapLoadFailed; // PLAYERBOT FIX: cache failed VMAP loads to prevent repeated attempts
std::bitset<MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS> _mmapLoadFailed; // PLAYERBOT FIX: cache failed MMAP loads to prevent repeated attempts
static constexpr Milliseconds CleanupInterval = 1min;