mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
[Performance] Pre-Compute CLE Server Lists (#4838)
* [Performance] Pre-Compute CLE Server Lists * Remove debug
This commit is contained in:
parent
c2989e019a
commit
ac1469bac2
@ -347,6 +347,7 @@ RULE_STRING(World, SupportedClients, "RoF2", "Comma-delimited list of clients to
|
||||
RULE_STRING(World, CustomFilesKey, "", "Enable if the server requires custom files and sends a key to validate. Empty string to disable. Example: eqcustom_v1")
|
||||
RULE_STRING(World, CustomFilesUrl, "github.com/knervous/eqnexus/releases", "URL to display at character select if client is missing custom files")
|
||||
RULE_INT(World, CustomFilesAdminLevel, 20, "Admin level at which custom file key is not required when CustomFilesKey is specified")
|
||||
RULE_BOOL(World, RealTimeCalculateGuilds, false, "(Temp feature flag) If true, guilds will be calculated in real time instead of at zone boot. This is a performance hit but allows for more dynamic guilds.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
|
||||
@ -42,11 +42,16 @@ extern ZSList zoneserver_list;
|
||||
uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
|
||||
|
||||
ClientList::ClientList()
|
||||
: CLStale_timer(10000)
|
||||
: CLStale_timer(10000),
|
||||
m_poll_cache_timer(6000)
|
||||
{
|
||||
NextCLEID = 1;
|
||||
|
||||
m_tick = std::make_unique<EQ::Timer>(5000, true, std::bind(&ClientList::OnTick, this, std::placeholders::_1));
|
||||
|
||||
// pre-allocate / pin memory for the zone server caches
|
||||
m_gm_zone_server_ids.reserve(512);
|
||||
m_guild_zone_server_ids.reserve(1024);
|
||||
}
|
||||
|
||||
ClientList::~ClientList() {
|
||||
@ -57,6 +62,10 @@ void ClientList::Process() {
|
||||
if (CLStale_timer.Check())
|
||||
CLCheckStale();
|
||||
|
||||
if (m_poll_cache_timer.Check()) {
|
||||
RebuildZoneServerCaches();
|
||||
}
|
||||
|
||||
LinkedListIterator<Client*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
@ -384,6 +393,7 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
||||
}
|
||||
else {
|
||||
cle->Update(zoneserver, scl);
|
||||
AddToZoneServerCaches(cle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -458,6 +468,7 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
||||
);
|
||||
|
||||
clientlist.Insert(cle);
|
||||
AddToZoneServerCaches(cle);
|
||||
zoneserver->ChangeWID(scl->charid, cle->GetID());
|
||||
}
|
||||
|
||||
@ -1857,71 +1868,97 @@ std::map<uint32, ClientListEntry *> ClientList::GetGuildClientsWithTributeOptIn(
|
||||
return guild_members;
|
||||
}
|
||||
|
||||
#include <unordered_set>
|
||||
void ClientList::RebuildZoneServerCaches()
|
||||
{
|
||||
// Clear without freeing memory (buckets stay allocated)
|
||||
m_gm_zone_server_ids.clear();
|
||||
m_guild_zone_server_ids.clear();
|
||||
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
iterator.Reset();
|
||||
|
||||
while (iterator.MoreElements()) {
|
||||
ClientListEntry* cle = iterator.GetData();
|
||||
|
||||
if (cle->Online() != CLE_Status::InZone || !cle->Server()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t server_id = cle->Server()->GetID();
|
||||
|
||||
// Track GM zone server
|
||||
if (cle->GetGM()) {
|
||||
m_gm_zone_server_ids.insert(server_id);
|
||||
}
|
||||
|
||||
// Track guild zone servers
|
||||
if (cle->GuildID() > 0) {
|
||||
auto& guild_set = m_guild_zone_server_ids[cle->GuildID()];
|
||||
guild_set.insert(server_id);
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> ClientList::GetGuildZoneServers(uint32 guild_id)
|
||||
{
|
||||
std::vector<uint32_t> zone_server_ids;
|
||||
std::unordered_set<uint32_t> seen_ids;
|
||||
if (RuleB(World, RealTimeCalculateGuilds)) {
|
||||
std::vector<uint32_t> zone_server_ids;
|
||||
std::unordered_set<uint32_t> seen_ids;
|
||||
|
||||
LinkedListIterator<ClientListEntry *> iterator(clientlist);
|
||||
LinkedListIterator<ClientListEntry *> iterator(clientlist);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ClientListEntry *cle = iterator.GetData();
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ClientListEntry *cle = iterator.GetData();
|
||||
|
||||
if (cle->Online() != CLE_Status::InZone) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cle->Server()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cle->GuildID() == guild_id) {
|
||||
uint32_t id = cle->Server()->GetID();
|
||||
if (seen_ids.insert(id).second) {
|
||||
zone_server_ids.emplace_back(id);
|
||||
if (cle->Online() != CLE_Status::InZone) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cle->Server()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cle->GuildID() == guild_id) {
|
||||
uint32_t id = cle->Server()->GetID();
|
||||
if (seen_ids.insert(id).second) {
|
||||
zone_server_ids.emplace_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
return zone_server_ids;
|
||||
}
|
||||
|
||||
return zone_server_ids;
|
||||
auto it = m_guild_zone_server_ids.find(guild_id);
|
||||
if (it == m_guild_zone_server_ids.end()) {
|
||||
return {};
|
||||
}
|
||||
return {it->second.begin(), it->second.end()};
|
||||
}
|
||||
|
||||
std::vector<uint32_t> ClientList::GetZoneServersWithGMs()
|
||||
void ClientList::AddToZoneServerCaches(ClientListEntry* cle)
|
||||
{
|
||||
std::vector<uint32_t> zone_server_ids;
|
||||
std::unordered_set<uint32_t> seen_ids;
|
||||
LinkedListIterator<ClientListEntry *> iterator(clientlist);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ClientListEntry *cle = iterator.GetData();
|
||||
|
||||
if (cle->Online() != CLE_Status::InZone) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cle->Server()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cle->Admin() > 0) {
|
||||
uint32_t id = cle->Server()->GetID();
|
||||
if (seen_ids.insert(id).second) {
|
||||
zone_server_ids.emplace_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
if (!cle || cle->Online() != CLE_Status::InZone || !cle->Server()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return zone_server_ids;
|
||||
uint32_t server_id = cle->Server()->GetID();
|
||||
|
||||
// Add GM zone server if applicable
|
||||
if (cle->GetGM()) {
|
||||
m_gm_zone_server_ids.insert(server_id);
|
||||
}
|
||||
|
||||
// Add guild zone server if applicable
|
||||
if (cle->GuildID() > 0) {
|
||||
m_guild_zone_server_ids[cle->GuildID()].insert(server_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,8 +60,6 @@ public:
|
||||
void CLCheckStale();
|
||||
void CLEKeepAlive(uint32 numupdates, uint32* wid);
|
||||
void CLEAdd(uint32 login_server_id, const char* login_server_name, const char* login_name, const char* login_key, int16 world_admin = AccountStatus::Player, uint32 ip_address = 0, uint8 is_local=0);
|
||||
std::vector<uint32_t> GetGuildZoneServers(uint32 guild_id);
|
||||
std::vector<uint32_t> GetZoneServersWithGMs();
|
||||
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
|
||||
bool IsAccountInGame(uint32 iLSID);
|
||||
|
||||
@ -78,6 +76,15 @@ public:
|
||||
void SendCharacterMessageID(const std::string& character_name, int chat_type, int eqstr_id, std::initializer_list<std::string> args = {});
|
||||
void SendCharacterMessageID(ClientListEntry* character, int chat_type, int eqstr_id, std::initializer_list<std::string> args = {});
|
||||
|
||||
void AddToZoneServerCaches(ClientListEntry* cle);
|
||||
void RebuildZoneServerCaches();
|
||||
|
||||
std::vector<uint32_t> GetGuildZoneServers(uint32 guild_id);
|
||||
inline std::vector<uint32_t> GetZoneServersWithGMs()
|
||||
{
|
||||
return {m_gm_zone_server_ids.begin(), m_gm_zone_server_ids.end()};
|
||||
}
|
||||
|
||||
private:
|
||||
void OnTick(EQ::Timer *t);
|
||||
inline uint32 GetNextCLEID() { return NextCLEID++; }
|
||||
@ -92,6 +99,11 @@ private:
|
||||
|
||||
|
||||
std::unique_ptr<EQ::Timer> m_tick;
|
||||
|
||||
// Zone server routing caches
|
||||
Timer m_poll_cache_timer;
|
||||
std::unordered_set<uint32_t> m_gm_zone_server_ids;
|
||||
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> m_guild_zone_server_ids;
|
||||
};
|
||||
|
||||
#endif /*CLIENTLIST_H_*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user