Reduced #repop time dramatically by taking down hundreds of individual SELECT/DELETE/INSERT queries in routines and bringing it down to very few

See: https://www.youtube.com/watch?v=9kSFbyTBuAk
This commit is contained in:
Akkadius 2015-02-08 05:01:58 -06:00
parent 1149f04389
commit cb81d956f6
6 changed files with 119 additions and 41 deletions

View File

@ -1,5 +1,9 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 02/06/2015 ==
Akkadius: Reduced #repop time dramatically by taking down hundreds of individual SELECT/DELETE/INSERT queries in routines and bringing it down to very few
See: https://www.youtube.com/watch?v=9kSFbyTBuAk
== 02/06/2015 ==
Uleat: Updated returns for Inventory and ItemInst const iterators. (const == const)
Uleat: Replaced 'iter_inst' and 'iter_contents' typedefs with their stl definitions

View File

@ -297,7 +297,7 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id)
}
}
database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), 0);
database.UpdateRespawnTime(spawn2_id, zone->GetInstanceID(), 0);
found_spawn->SetCurrentNPCID(npcid);
auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading());
@ -2388,7 +2388,7 @@ void QuestManager::UpdateSpawnTimer(uint32 id, uint32 newTime)
{
bool found = false;
database.UpdateSpawn2Timeleft(id, 0, (newTime/1000));
database.UpdateRespawnTime(id, 0, (newTime/1000));
LinkedListIterator<Spawn2*> iterator(zone->spawn2_list);
iterator.Reset();
while (iterator.MoreElements())

View File

@ -214,9 +214,6 @@ bool Spawn2::Process() {
if(IsDespawned)
return true;
if(spawn2_id)
database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), 0);
currentnpcid = npcid;
NPC* npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), FlyMode3);
@ -348,7 +345,7 @@ void Spawn2::DeathReset(bool realdeath)
//if we have a valid spawn id
if(spawn2_id)
{
database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), (cur/1000));
database.UpdateRespawnTime(spawn2_id, zone->GetInstanceID(), (cur/1000));
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset by death, repop in %d ms", spawn2_id, timer.GetRemainingTime());
//store it to database too
}
@ -356,27 +353,91 @@ void Spawn2::DeathReset(bool realdeath)
bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay) {
std::unordered_map<uint32, uint32> spawn_times;
timeval tv;
gettimeofday(&tv, nullptr);
std::string spawn_query = StringFormat(
"SELECT "
"respawn_times.id, "
"respawn_times.`start`, "
"respawn_times.duration "
"FROM "
"respawn_times "
"WHERE instance_id = %u",
zone->GetInstanceID()
);
auto results = QueryDatabase(spawn_query);
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 start_duration = atoi(row[1]) > 0 ? atoi(row[1]) : 0;
uint32 end_duration = atoi(row[2]) > 0 ? atoi(row[2]) : 0;
/* Our current time was expired */
if ((start_duration + end_duration) <= tv.tv_sec) {
spawn_times[atoi(row[0])] = 0;
}
/* We still have time left on this timer */
else {
spawn_times[atoi(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000;
}
}
const char *zone_name = database.GetZoneName(zoneid);
std::string query = StringFormat("SELECT id, spawngroupID, x, y, z, heading, "
"respawntime, variance, pathgrid, _condition, "
"cond_value, enabled, animation FROM spawn2 "
std::string query = StringFormat(
"SELECT "
"id, "
"spawngroupID, "
"x, "
"y, "
"z, "
"heading, "
"respawntime, "
"variance, "
"pathgrid, "
"_condition, "
"cond_value, "
"enabled, "
"animation "
"FROM "
"spawn2 "
"WHERE zone = '%s' AND version = %u",
zone_name, version);
auto results = QueryDatabase(query);
zone_name,
version
);
results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
Spawn2* newSpawn = 0;
bool perl_enabled = atoi(row[11]) == 1? true: false;
uint32 spawnLeft = (GetSpawnTimeLeft(atoi(row[0]), zone->GetInstanceID()) * 1000);
newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), atof(row[3]), atof(row[4]),
atof(row[5]), atoi(row[6]), atoi(row[7]), spawnLeft, atoi(row[8]),
atoi(row[9]), atoi(row[10]), perl_enabled, (EmuAppearance)atoi(row[12]));
uint32 spawn_time_left = 0;
Spawn2* new_spawn = 0;
bool perl_enabled = atoi(row[11]) == 1 ? true : false;
spawn2_list.Insert(newSpawn);
if (spawn_times.count(atoi(row[0])) != 0)
spawn_time_left = spawn_times[atoi(row[0])];
new_spawn = new Spawn2( //
atoi(row[0]), // uint32 in_spawn2_id
atoi(row[1]), // uint32 spawngroup_id
atof(row[2]), // float in_x
atof(row[3]), // float in_y
atof(row[4]), // float in_z
atof(row[5]), // float in_heading
atoi(row[6]), // uint32 respawn
atoi(row[7]), // uint32 variance
spawn_time_left, // uint32 timeleft
atoi(row[8]), // uint32 grid
atoi(row[9]), // uint16 in_cond_id
atoi(row[10]), // int16 in_min_value
perl_enabled, // bool in_enabled
(EmuAppearance)atoi(row[12]) // EmuAppearance anim
);
spawn2_list.Insert(new_spawn);
}
return true;
@ -427,8 +488,6 @@ bool ZoneDatabase::CreateSpawn2(Client *client, uint32 spawngroup, const char* z
if (results.RowsAffected() != 1)
return false;
if(client)
return true;
}

View File

@ -931,6 +931,9 @@ bool Zone::Init(bool iStaticZone) {
Log.Out(Logs::General, Logs::Error, "Loading World Objects failed. continuing.");
}
Log.Out(Logs::General, Logs::Status, "Flushing old respawn timers...");
database.QueryDatabase("DELETE FROM `respawn_times` WHERE (`start` + `duration`) < UNIX_TIMESTAMP(NOW())");
//load up the zone's doors (prints inside)
zone->LoadZoneDoors(zone->GetShortName(), zone->GetInstanceVersion());
zone->LoadBlockedSpells(zone->GetZoneID());

View File

@ -185,28 +185,40 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
return true;
}
//updates or clears the respawn time in the database for the current spawn id
void ZoneDatabase::UpdateSpawn2Timeleft(uint32 id, uint16 instance_id, uint32 timeleft)
void ZoneDatabase::UpdateRespawnTime(uint32 spawn2_id, uint16 instance_id, uint32 time_left)
{
timeval tv;
gettimeofday(&tv, nullptr);
uint32 cur = tv.tv_sec;
uint32 current_time = tv.tv_sec;
//if we pass timeleft as 0 that means we clear from respawn time
//otherwise we update with a REPLACE INTO
if(timeleft == 0) {
std::string query = StringFormat("DELETE FROM respawn_times WHERE id=%lu AND instance_id = %lu",(unsigned long)id, (unsigned long)instance_id);
auto results = QueryDatabase(query);
/* If we pass timeleft as 0 that means we clear from respawn time
otherwise we update with a REPLACE INTO
*/
if(time_left == 0) {
std::string query = StringFormat("DELETE FROM `respawn_times` WHERE `id` = %u AND `instance_id` = %u", spawn2_id, instance_id);
QueryDatabase(query);
return;
}
std::string query = StringFormat("REPLACE INTO respawn_times (id, start, duration, instance_id) "
"VALUES (%lu, %lu, %lu, %lu)",
(unsigned long)id, (unsigned long)cur,
(unsigned long)timeleft, (unsigned long)instance_id);
auto results = QueryDatabase(query);
if (!results.Success())
std::string query = StringFormat(
"REPLACE INTO `respawn_times` "
"(id, "
"start, "
"duration, "
"instance_id) "
"VALUES "
"(%u, "
"%u, "
"%u, "
"%u)",
spawn2_id,
current_time,
time_left,
instance_id
);
QueryDatabase(query);
return;
}

View File

@ -365,7 +365,7 @@ public:
bool PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay = 0);
Spawn2* LoadSpawn2(LinkedList<Spawn2*> &spawn2_list, uint32 spawn2id, uint32 timeleft);
bool CreateSpawn2(Client *c, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value);
void UpdateSpawn2Timeleft(uint32 id, uint16 instance_id,uint32 timeleft);
void UpdateRespawnTime(uint32 id, uint16 instance_id,uint32 timeleft);
uint32 GetSpawnTimeLeft(uint32 id, uint16 instance_id);
void UpdateSpawn2Status(uint32 id, uint8 new_status);