refactor(Core/LFG): Reduce memory allocations in LFG hot paths (#25064)

Co-authored-by: blinkysc <blinkysc@users.noreply.github.com>
Co-authored-by: sudlud <sudlud@users.noreply.github.com>
This commit is contained in:
blinkysc
2026-07-05 09:52:41 -05:00
committed by GitHub
parent 523bd83ad6
commit fe82e9faf8
3 changed files with 52 additions and 60 deletions

View File

@@ -826,7 +826,6 @@ namespace lfg
return; return;
} }
std::string debugNames = "";
if (grp) // Begin rolecheck if (grp) // Begin rolecheck
{ {
// Create new rolecheck // Create new rolecheck
@@ -857,9 +856,6 @@ namespace lfg
if (!isContinue) if (!isContinue)
SetSelectedDungeons(pguid, dungeons); SetSelectedDungeons(pguid, dungeons);
roleCheck.roles[pguid] = 0; roleCheck.roles[pguid] = 0;
if (!debugNames.empty())
debugNames.append(", ");
debugNames.append(plrg->GetName());
} }
} }
// Update leader role // Update leader role
@@ -886,16 +882,7 @@ namespace lfg
player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment)); player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment));
SetState(guid, LFG_STATE_QUEUED); SetState(guid, LFG_STATE_QUEUED);
SetRoles(guid, roles); SetRoles(guid, roles);
debugNames.append(player->GetName());
} }
/*if (sLog->ShouldLog(LOG_FILTER_LFG, LOG_LEVEL_DEBUG))
{
std::ostringstream o;
o << "LFGMgr::Join: [" << guid << "] joined (" << (grp ? "group" : "player") << ") Members: " << debugNames.c_str()
<< ". Dungeons (" << uint32(dungeons.size()) << "): " << ConcatenateDungeons(dungeons);
LOG_DEBUG("lfg", "{}", o.str());
}*/
} }
void LFGMgr::ToggleTesting() void LFGMgr::ToggleTesting()
@@ -1099,10 +1086,7 @@ namespace lfg
int32 spellDamage, spellHeal; int32 spellDamage, spellHeal;
uint32 dungeonId, encounterMask, maxPower; uint32 dungeonId, encounterMask, maxPower;
uint32 deletedCounter, groupCounter, playerCounter; uint32 deletedCounter, groupCounter, playerCounter;
ByteBuffer buffer_deleted, buffer_groups, buffer_players;
std::string emptyComment; std::string emptyComment;
GuidSet deletedGroups, deletedGroupsToErase;
RBInternalInfoMap copy;
for (uint8 team = 0; team < 2; ++team) for (uint8 team = 0; team < 2; ++team)
{ {
@@ -1207,18 +1191,18 @@ namespace lfg
} }
} }
copy.clear(); _rbCopy.clear();
copy = currInternalInfoMap; // will be saved as prev at the end _rbCopy = currInternalInfoMap; // will be saved as prev at the end
// compare prev with curr to build difference packet // compare prev with curr to build difference packet
deletedCounter = 0; deletedCounter = 0;
groupCounter = 0; groupCounter = 0;
playerCounter = 0; playerCounter = 0;
buffer_deleted.clear(); _rbBufferDeleted.clear();
buffer_groups.clear(); _rbBufferGroups.clear();
buffer_players.clear(); _rbBufferPlayers.clear();
deletedGroups.clear(); _rbDeletedGroups.clear();
deletedGroupsToErase.clear(); _rbDeletedGroupsToErase.clear();
RBInternalInfoMap& prevInternalInfoMap = RBInternalInfoStorePrev[team][dungeonId]; RBInternalInfoMap& prevInternalInfoMap = RBInternalInfoStorePrev[team][dungeonId];
RBInternalInfoMap::iterator iter, iterTmp; RBInternalInfoMap::iterator iter, iterTmp;
@@ -1228,50 +1212,51 @@ namespace lfg
if (iter == currInternalInfoMap.end()) // was -> isn't if (iter == currInternalInfoMap.end()) // was -> isn't
{ {
if (sitr->second.isGroupLeader) if (sitr->second.isGroupLeader)
deletedGroups.insert(sitr->second.groupGuid); _rbDeletedGroups.insert(sitr->second.groupGuid);
++deletedCounter; ++deletedCounter;
buffer_deleted << sitr->second.guid; _rbBufferDeleted << sitr->second.guid;
} }
else // was -> is else // was -> is
{ {
if (sitr->second.isGroupLeader) // was a leader if (sitr->second.isGroupLeader) // was a leader
{ {
if (!iter->second.isGroupLeader) // leader -> no longer a leader if (!iter->second.isGroupLeader) // leader -> no longer a leader
deletedGroups.insert(sitr->second.groupGuid); _rbDeletedGroups.insert(sitr->second.groupGuid);
else if (sitr->second.groupGuid != iter->second.groupGuid) // leader -> leader of another group else if (sitr->second.groupGuid != iter->second.groupGuid) // leader -> leader of another group
{ {
deletedGroups.insert(sitr->second.groupGuid); _rbDeletedGroups.insert(sitr->second.groupGuid);
deletedGroupsToErase.insert(iter->second.groupGuid); _rbDeletedGroupsToErase.insert(iter->second.groupGuid);
++groupCounter; ++groupCounter;
RBPacketAppendGroup(iter->second, buffer_groups); RBPacketAppendGroup(iter->second, _rbBufferGroups);
} }
else if (sitr->second.comment != iter->second.comment || sitr->second.encounterMask != iter->second.encounterMask || sitr->second.instanceGuid != iter->second.instanceGuid) // leader -> nothing changed else if (sitr->second.comment != iter->second.comment || sitr->second.encounterMask != iter->second.encounterMask || sitr->second.instanceGuid != iter->second.instanceGuid) // leader -> nothing changed
{ {
++groupCounter; ++groupCounter;
RBPacketAppendGroup(iter->second, buffer_groups); RBPacketAppendGroup(iter->second, _rbBufferGroups);
} }
} }
else if (iter->second.isGroupLeader) // wasn't a leader -> is a leader else if (iter->second.isGroupLeader) // wasn't a leader -> is a leader
{ {
deletedGroupsToErase.insert(iter->second.groupGuid); _rbDeletedGroupsToErase.insert(iter->second.groupGuid);
++groupCounter; ++groupCounter;
RBPacketAppendGroup(iter->second, buffer_groups); RBPacketAppendGroup(iter->second, _rbBufferGroups);
} }
if (!iter->second._online) // if offline, copy previous stats (itemLevel, talents, area, etc.) if (!iter->second._online) // if offline, copy previous stats (itemLevel, talents, area, etc.)
{ {
iterTmp = copy.find(sitr->first); // copied container is for building a full packet, so modify it there (currInternalInfoMap is erased) iterTmp = _rbCopy.find(sitr->first); // copied container is for building a full packet, so modify it there (currInternalInfoMap is erased)
iterTmp->second.CopyStats(sitr->second); iterTmp->second.CopyStats(sitr->second);
if (!sitr->second.PlayerSameAs(iterTmp->second)) // player info changed if (!sitr->second.PlayerSameAs(iterTmp->second)) // player info changed
{ {
++playerCounter; ++playerCounter;
RBPacketAppendPlayer(iterTmp->second, buffer_players); RBPacketAppendPlayer(iterTmp->second, _rbBufferPlayers);
} }
} }
else if (!sitr->second.PlayerSameAs(iter->second)) // player info changed else if (!sitr->second.PlayerSameAs(iter->second)) // player info changed
{ {
++playerCounter; ++playerCounter;
RBPacketAppendPlayer(iter->second, buffer_players); RBPacketAppendPlayer(iter->second, _rbBufferPlayers);
} }
currInternalInfoMap.erase(iter); currInternalInfoMap.erase(iter);
} }
@@ -1281,38 +1266,38 @@ namespace lfg
{ {
if (sitr->second.isGroupLeader) if (sitr->second.isGroupLeader)
{ {
deletedGroupsToErase.insert(sitr->second.groupGuid); _rbDeletedGroupsToErase.insert(sitr->second.groupGuid);
++groupCounter; ++groupCounter;
RBPacketAppendGroup(sitr->second, buffer_groups); RBPacketAppendGroup(sitr->second, _rbBufferGroups);
} }
++playerCounter; ++playerCounter;
RBPacketAppendPlayer(sitr->second, buffer_players); RBPacketAppendPlayer(sitr->second, _rbBufferPlayers);
} }
if (!deletedGroupsToErase.empty()) if (!_rbDeletedGroupsToErase.empty())
{ {
for (ObjectGuid const& toErase : deletedGroupsToErase) for (ObjectGuid const& toErase : _rbDeletedGroupsToErase)
{ {
deletedGroups.erase(toErase); _rbDeletedGroups.erase(toErase);
} }
} }
if (!deletedGroups.empty()) if (!_rbDeletedGroups.empty())
{ {
for (ObjectGuid const& deletedGroup : deletedGroups) for (ObjectGuid const& deletedGroup : _rbDeletedGroups)
{ {
++deletedCounter; ++deletedCounter;
buffer_deleted << deletedGroup; _rbBufferDeleted << deletedGroup;
} }
} }
WorldPacket differencePacket(SMSG_UPDATE_LFG_LIST, 1000); WorldPacket differencePacket(SMSG_UPDATE_LFG_LIST, 1000);
RBPacketBuildDifference(differencePacket, dungeonId, deletedCounter, buffer_deleted, groupCounter, buffer_groups, playerCounter, buffer_players); RBPacketBuildDifference(differencePacket, dungeonId, deletedCounter, _rbBufferDeleted, groupCounter, _rbBufferGroups, playerCounter, _rbBufferPlayers);
WorldPacket fullPacket(SMSG_UPDATE_LFG_LIST, 1000); WorldPacket fullPacket(SMSG_UPDATE_LFG_LIST, 1000);
RBPacketBuildFull(fullPacket, dungeonId, copy); RBPacketBuildFull(fullPacket, dungeonId, _rbCopy);
RBCacheStore[team][dungeonId] = fullPacket; RBCacheStore[team][dungeonId] = fullPacket;
prevInternalInfoMap = copy; prevInternalInfoMap = _rbCopy;
currInternalInfoMap.clear(); currInternalInfoMap.clear();
if (entryInfoMap.empty()) if (entryInfoMap.empty())
@@ -1403,44 +1388,44 @@ namespace lfg
buffer << (uint32)info.encounterMask; buffer << (uint32)info.encounterMask;
} }
void LFGMgr::RBPacketBuildDifference(WorldPacket& differencePacket, uint32 dungeonId, uint32 deletedCounter, ByteBuffer& buffer_deleted, uint32 groupCounter, ByteBuffer& buffer_groups, uint32 playerCounter, ByteBuffer& buffer_players) void LFGMgr::RBPacketBuildDifference(WorldPacket& differencePacket, uint32 dungeonId, uint32 deletedCounter, ByteBuffer const& bufferDeleted, uint32 groupCounter, ByteBuffer const& bufferGroups, uint32 playerCounter, ByteBuffer const& bufferPlayers)
{ {
differencePacket << (uint32)LFG_TYPE_RAID; differencePacket << (uint32)LFG_TYPE_RAID;
differencePacket << (uint32)dungeonId; differencePacket << (uint32)dungeonId;
differencePacket << (uint8)1; differencePacket << (uint8)1;
differencePacket << (uint32)deletedCounter; differencePacket << (uint32)deletedCounter;
differencePacket.append(buffer_deleted); differencePacket.append(bufferDeleted);
differencePacket << (uint32)groupCounter; differencePacket << (uint32)groupCounter;
differencePacket << (uint32)0; differencePacket << (uint32)0;
differencePacket.append(buffer_groups); differencePacket.append(bufferGroups);
differencePacket << (uint32)playerCounter; differencePacket << (uint32)playerCounter;
differencePacket << (uint32)0; differencePacket << (uint32)0;
differencePacket.append(buffer_players); differencePacket.append(bufferPlayers);
} }
void LFGMgr::RBPacketBuildFull(WorldPacket& fullPacket, uint32 dungeonId, RBInternalInfoMap& infoMap) void LFGMgr::RBPacketBuildFull(WorldPacket& fullPacket, uint32 dungeonId, RBInternalInfoMap const& infoMap)
{ {
fullPacket << (uint32)LFG_TYPE_RAID; fullPacket << (uint32)LFG_TYPE_RAID;
fullPacket << (uint32)dungeonId; fullPacket << (uint32)dungeonId;
fullPacket << (uint8)0; fullPacket << (uint8)0;
uint32 groupCounter = 0, playerCounter = 0; uint32 groupCounter = 0, playerCounter = 0;
ByteBuffer buffer_groups, buffer_players; ByteBuffer bufferGroups, bufferPlayers;
for (RBInternalInfoMap::const_iterator itr = infoMap.begin(); itr != infoMap.end(); ++itr) for (RBInternalInfoMap::const_iterator itr = infoMap.begin(); itr != infoMap.end(); ++itr)
{ {
if (itr->second.isGroupLeader) if (itr->second.isGroupLeader)
{ {
++groupCounter; ++groupCounter;
RBPacketAppendGroup(itr->second, buffer_groups); RBPacketAppendGroup(itr->second, bufferGroups);
} }
++playerCounter; ++playerCounter;
RBPacketAppendPlayer(itr->second, buffer_players); RBPacketAppendPlayer(itr->second, bufferPlayers);
} }
fullPacket << (uint32)groupCounter; fullPacket << (uint32)groupCounter;
fullPacket << (uint32)0; fullPacket << (uint32)0;
fullPacket.append(buffer_groups); fullPacket.append(bufferGroups);
fullPacket << (uint32)playerCounter; fullPacket << (uint32)playerCounter;
fullPacket << (uint32)0; fullPacket << (uint32)0;
fullPacket.append(buffer_players); fullPacket.append(bufferPlayers);
} }
// pussywizard: // pussywizard:

View File

@@ -20,6 +20,7 @@
#include <utility> #include <utility>
#include "ByteBuffer.h"
#include "DBCStructure.h" #include "DBCStructure.h"
#include "Field.h" #include "Field.h"
#include "LFG.h" #include "LFG.h"
@@ -562,8 +563,8 @@ namespace lfg
void SendRaidBrowserJoinedPacket(Player* p, LfgDungeonSet& dungeons, std::string comment); void SendRaidBrowserJoinedPacket(Player* p, LfgDungeonSet& dungeons, std::string comment);
void RBPacketAppendGroup(const RBInternalInfo& info, ByteBuffer& buffer); void RBPacketAppendGroup(const RBInternalInfo& info, ByteBuffer& buffer);
void RBPacketAppendPlayer(const RBInternalInfo& info, ByteBuffer& buffer); void RBPacketAppendPlayer(const RBInternalInfo& info, ByteBuffer& buffer);
void RBPacketBuildDifference(WorldPacket& differencePacket, uint32 dungeonId, uint32 deletedCounter, ByteBuffer& buffer_deleted, uint32 groupCounter, ByteBuffer& buffer_groups, uint32 playerCounter, ByteBuffer& buffer_players); void RBPacketBuildDifference(WorldPacket& differencePacket, uint32 dungeonId, uint32 deletedCounter, ByteBuffer const& bufferDeleted, uint32 groupCounter, ByteBuffer const& bufferGroups, uint32 playerCounter, ByteBuffer const& bufferPlayers);
void RBPacketBuildFull(WorldPacket& fullPacket, uint32 dungeonId, RBInternalInfoMap& infoMap); void RBPacketBuildFull(WorldPacket& fullPacket, uint32 dungeonId, RBInternalInfoMap const& infoMap);
// LfgQueue // LfgQueue
/// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON) /// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON)
@@ -627,6 +628,12 @@ namespace lfg
uint32 lastProposalId; ///< pussywizard, store it here because of splitting LFGMgr update into tasks uint32 lastProposalId; ///< pussywizard, store it here because of splitting LFGMgr update into tasks
uint32 m_raidBrowserUpdateTimer[2]; ///< pussywizard uint32 m_raidBrowserUpdateTimer[2]; ///< pussywizard
uint32 m_raidBrowserLastUpdatedDungeonId[2]; ///< pussywizard: for 2 factions uint32 m_raidBrowserLastUpdatedDungeonId[2]; ///< pussywizard: for 2 factions
ByteBuffer _rbBufferDeleted;
ByteBuffer _rbBufferGroups;
ByteBuffer _rbBufferPlayers;
GuidSet _rbDeletedGroups;
GuidSet _rbDeletedGroupsToErase;
RBInternalInfoMap _rbCopy;
LfgQueueContainer QueuesStore; ///< Queues LfgQueueContainer QueuesStore; ///< Queues
LfgCachedDungeonContainer CachedDungeonMapStore; ///< Stores all dungeons by groupType LfgCachedDungeonContainer CachedDungeonMapStore; ///< Stores all dungeons by groupType

View File

@@ -374,7 +374,7 @@ namespace lfg
LfgDungeonSet temporal; LfgDungeonSet temporal;
LfgDungeonSet& dungeons = QueueDataStore[check.guids[i]].dungeons; LfgDungeonSet& dungeons = QueueDataStore[check.guids[i]].dungeons;
std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin())); std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin()));
proposalDungeons = temporal; std::swap(proposalDungeons, temporal);
} }
if (proposalDungeons.empty()) if (proposalDungeons.empty())