mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 18:51: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, 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_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_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_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
|
|||||||
@ -42,11 +42,16 @@ extern ZSList zoneserver_list;
|
|||||||
uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
|
uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
|
||||||
|
|
||||||
ClientList::ClientList()
|
ClientList::ClientList()
|
||||||
: CLStale_timer(10000)
|
: CLStale_timer(10000),
|
||||||
|
m_poll_cache_timer(6000)
|
||||||
{
|
{
|
||||||
NextCLEID = 1;
|
NextCLEID = 1;
|
||||||
|
|
||||||
m_tick = std::make_unique<EQ::Timer>(5000, true, std::bind(&ClientList::OnTick, this, std::placeholders::_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() {
|
ClientList::~ClientList() {
|
||||||
@ -57,6 +62,10 @@ void ClientList::Process() {
|
|||||||
if (CLStale_timer.Check())
|
if (CLStale_timer.Check())
|
||||||
CLCheckStale();
|
CLCheckStale();
|
||||||
|
|
||||||
|
if (m_poll_cache_timer.Check()) {
|
||||||
|
RebuildZoneServerCaches();
|
||||||
|
}
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(list);
|
LinkedListIterator<Client*> iterator(list);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
@ -384,6 +393,7 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cle->Update(zoneserver, scl);
|
cle->Update(zoneserver, scl);
|
||||||
|
AddToZoneServerCaches(cle);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -458,6 +468,7 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
|||||||
);
|
);
|
||||||
|
|
||||||
clientlist.Insert(cle);
|
clientlist.Insert(cle);
|
||||||
|
AddToZoneServerCaches(cle);
|
||||||
zoneserver->ChangeWID(scl->charid, cle->GetID());
|
zoneserver->ChangeWID(scl->charid, cle->GetID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1857,10 +1868,43 @@ std::map<uint32, ClientListEntry *> ClientList::GetGuildClientsWithTributeOptIn(
|
|||||||
return guild_members;
|
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> ClientList::GetGuildZoneServers(uint32 guild_id)
|
||||||
{
|
{
|
||||||
|
if (RuleB(World, RealTimeCalculateGuilds)) {
|
||||||
std::vector<uint32_t> zone_server_ids;
|
std::vector<uint32_t> zone_server_ids;
|
||||||
std::unordered_set<uint32_t> seen_ids;
|
std::unordered_set<uint32_t> seen_ids;
|
||||||
|
|
||||||
@ -1893,35 +1937,28 @@ std::vector<uint32_t> ClientList::GetGuildZoneServers(uint32 guild_id)
|
|||||||
return zone_server_ids;
|
return zone_server_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> ClientList::GetZoneServersWithGMs()
|
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()};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientList::AddToZoneServerCaches(ClientListEntry* cle)
|
||||||
{
|
{
|
||||||
std::vector<uint32_t> zone_server_ids;
|
if (!cle || cle->Online() != CLE_Status::InZone || !cle->Server()) {
|
||||||
std::unordered_set<uint32_t> seen_ids;
|
return;
|
||||||
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()) {
|
uint32_t server_id = cle->Server()->GetID();
|
||||||
iterator.Advance();
|
|
||||||
continue;
|
// Add GM zone server if applicable
|
||||||
|
if (cle->GetGM()) {
|
||||||
|
m_gm_zone_server_ids.insert(server_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cle->Admin() > 0) {
|
// Add guild zone server if applicable
|
||||||
uint32_t id = cle->Server()->GetID();
|
if (cle->GuildID() > 0) {
|
||||||
if (seen_ids.insert(id).second) {
|
m_guild_zone_server_ids[cle->GuildID()].insert(server_id);
|
||||||
zone_server_ids.emplace_back(id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator.Advance();
|
|
||||||
}
|
|
||||||
|
|
||||||
return zone_server_ids;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -60,8 +60,6 @@ public:
|
|||||||
void CLCheckStale();
|
void CLCheckStale();
|
||||||
void CLEKeepAlive(uint32 numupdates, uint32* wid);
|
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);
|
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);
|
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
|
||||||
bool IsAccountInGame(uint32 iLSID);
|
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(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 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:
|
private:
|
||||||
void OnTick(EQ::Timer *t);
|
void OnTick(EQ::Timer *t);
|
||||||
inline uint32 GetNextCLEID() { return NextCLEID++; }
|
inline uint32 GetNextCLEID() { return NextCLEID++; }
|
||||||
@ -92,6 +99,11 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
std::unique_ptr<EQ::Timer> m_tick;
|
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_*/
|
#endif /*CLIENTLIST_H_*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user