From c986da9c77078cb5b4e2533bcc35d1dd5c940be7 Mon Sep 17 00:00:00 2001 From: agatho Date: Mon, 2 Feb 2026 15:39:30 +0100 Subject: [PATCH] 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 Signed-off-by: luis --- .../EXTREME_LAG_ROOT_CAUSE_ANALYSIS.md | 25 ++++++++++++++++++- src/server/game/Maps/TerrainMgr.cpp | 16 +++++++++++- src/server/game/Maps/TerrainMgr.h | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.claude/analysis/EXTREME_LAG_ROOT_CAUSE_ANALYSIS.md b/.claude/analysis/EXTREME_LAG_ROOT_CAUSE_ANALYSIS.md index 9d88cca17..628775d83 100644 --- a/.claude/analysis/EXTREME_LAG_ROOT_CAUSE_ANALYSIS.md +++ b/.claude/analysis/EXTREME_LAG_ROOT_CAUSE_ANALYSIS.md @@ -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 diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp index 9f6e428e1..123fd7427 100644 --- a/src/server/game/Maps/TerrainMgr.cpp +++ b/src/server/game/Maps/TerrainMgr.cpp @@ -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; diff --git a/src/server/game/Maps/TerrainMgr.h b/src/server/game/Maps/TerrainMgr.h index 08535ebe9..df47de23c 100644 --- a/src/server/game/Maps/TerrainMgr.h +++ b/src/server/game/Maps/TerrainMgr.h @@ -116,6 +116,7 @@ private: std::array _loadedGrids; std::bitset _gridFileExists; // cache what grids are available for this map (not including parent/child maps) std::bitset _vmapLoadFailed; // PLAYERBOT FIX: cache failed VMAP loads to prevent repeated attempts + std::bitset _mmapLoadFailed; // PLAYERBOT FIX: cache failed MMAP loads to prevent repeated attempts static constexpr Milliseconds CleanupInterval = 1min;