From 34598bfccf6c9bad29be150cbf76de7e08d39543 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Sun, 25 Feb 2024 16:08:15 +0100 Subject: [PATCH] feat(Core/UpdateTime): Improve diff time measurement. (#18387) * feat(Core/UpdateTime): Improve diff time measurement. * Codestyle fixes --- src/server/game/Time/UpdateTime.cpp | 53 ++++++++++++++++++++++- src/server/game/Time/UpdateTime.h | 7 +++ src/server/scripts/Commands/cs_server.cpp | 8 +++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/server/game/Time/UpdateTime.cpp b/src/server/game/Time/UpdateTime.cpp index 43cb4a38a..8aa9592b7 100644 --- a/src/server/game/Time/UpdateTime.cpp +++ b/src/server/game/Time/UpdateTime.cpp @@ -19,6 +19,8 @@ #include "Config.h" #include "Log.h" #include "Timer.h" +#include +#include // create instance WorldUpdateTime sWorldUpdateTime; @@ -71,8 +73,34 @@ uint32 UpdateTime::GetLastUpdateTime() const return _updateTimeDataTable[_updateTimeTableIndex != 0 ? _updateTimeTableIndex - 1 : _updateTimeDataTable.size() - 1]; } +uint32 UpdateTime::GetDatasetSize() const +{ + return _updateTimeDataTable[_updateTimeDataTable.size() - 1] == 0 ? _updateTimeTableIndex : _orderedUpdateTimeDataTable.size(); +} + +uint32 UpdateTime::GetPercentile(uint8 p) +{ + if (_needsReorder) + SortUpdateTimeDataTable(); + + // Calculate the index of the element corresponding to the percentile + double index = (double(p) / 100.0) * (GetDatasetSize() - 1); + + // If the index is an integer, return the value at that index + if (index == floor(index)) + return _orderedUpdateTimeDataTable[index]; + + // Otherwise, perform linear interpolation + int lowerIndex = floor(index); + int upperIndex = ceil(index); + double fraction = index - lowerIndex; + + return _orderedUpdateTimeDataTable[lowerIndex] * (1 - fraction) + _orderedUpdateTimeDataTable[upperIndex] * fraction; +} + void UpdateTime::UpdateWithDiff(uint32 diff) { + _needsReorder = true; _totalUpdateTime = _totalUpdateTime - _updateTimeDataTable[_updateTimeTableIndex] + diff; _updateTimeDataTable[_updateTimeTableIndex] = diff; @@ -100,6 +128,26 @@ void UpdateTime::RecordUpdateTimeReset() _recordedTime = GetTimeMS(); } +void UpdateTime::SortUpdateTimeDataTable() +{ + if (!_needsReorder) + return; + + auto endUpdateTable = _updateTimeDataTable.end(); + if (!_updateTimeDataTable[_updateTimeDataTable.size() - 1]) + endUpdateTable = std::next(_updateTimeDataTable.begin(), _updateTimeTableIndex); + + std::copy(_updateTimeDataTable.begin(), endUpdateTable, _orderedUpdateTimeDataTable.begin()); + + auto endOrderedUpdateTable = _orderedUpdateTimeDataTable.end(); + if (!_updateTimeDataTable[_updateTimeDataTable.size() - 1]) + endOrderedUpdateTable = std::next(_orderedUpdateTimeDataTable.begin(), _updateTimeTableIndex); + + std::sort(_orderedUpdateTimeDataTable.begin(), endOrderedUpdateTable); + + _needsReorder = false; +} + void WorldUpdateTime::LoadFromConfig() { _recordUpdateTimeInverval = Milliseconds(sConfigMgr->GetOption("RecordUpdateTimeDiffInterval", 60000)); @@ -117,7 +165,10 @@ void WorldUpdateTime::RecordUpdateTime(Milliseconds gameTimeMs, uint32 diff, uin { if (GetMSTimeDiff(_lastRecordTime, gameTimeMs) > _recordUpdateTimeInverval) { - LOG_INFO("time.update", "Update time diff: {}. Players online: {}.", GetAverageUpdateTime(), sessionCount); + LOG_INFO("time.update", "Last {} diffs summary with {} players online:", GetDatasetSize(), sessionCount); + LOG_INFO("time.update", " - Mean: {};", GetAverageUpdateTime()); + LOG_INFO("time.update", " - Median: {};", GetPercentile(50)); + LOG_INFO("time.update", " - Percentiles (95, 99, max): {}, {}, {}.", GetPercentile(95), GetPercentile(99), GetPercentile(100)); _lastRecordTime = gameTimeMs; } } diff --git a/src/server/game/Time/UpdateTime.h b/src/server/game/Time/UpdateTime.h index b95f74060..356eb0526 100644 --- a/src/server/game/Time/UpdateTime.h +++ b/src/server/game/Time/UpdateTime.h @@ -35,6 +35,8 @@ public: uint32 GetMaxUpdateTime() const; uint32 GetMaxUpdateTimeOfCurrentTable() const; uint32 GetLastUpdateTime() const; + uint32 GetDatasetSize() const; + uint32 GetPercentile(uint8 p); void UpdateWithDiff(uint32 diff); @@ -43,6 +45,8 @@ public: protected: UpdateTime(); + void SortUpdateTimeDataTable(); + private: DiffTableArray _updateTimeDataTable; uint32 _averageUpdateTime; @@ -52,6 +56,9 @@ private: uint32 _maxUpdateTimeOfLastTable; uint32 _maxUpdateTimeOfCurrentTable; + DiffTableArray _orderedUpdateTimeDataTable; + bool _needsReorder; + Milliseconds _recordedTime; }; diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 25adccc20..a6a20c108 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -271,7 +271,13 @@ public: handler->PSendSysMessage("Connection peak: %u.", connPeak); handler->PSendSysMessage(LANG_UPTIME, secsToTimeString(GameTime::GetUptime().count()).c_str()); - handler->PSendSysMessage("Update time diff: %ums, average: %ums.", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetAverageUpdateTime()); + handler->PSendSysMessage("Update time diff: %ums. Last %d diffs summary:", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetDatasetSize()); + handler->PSendSysMessage("- Mean: %ums", sWorldUpdateTime.GetAverageUpdateTime()); + handler->PSendSysMessage("- Median: %ums", sWorldUpdateTime.GetPercentile(50)); + handler->PSendSysMessage("- Percentiles (95, 99, max): %ums, %ums, %ums", + sWorldUpdateTime.GetPercentile(95), + sWorldUpdateTime.GetPercentile(99), + sWorldUpdateTime.GetPercentile(100)); //! Can't use sWorld->ShutdownMsg here in case of console command if (sWorld->IsShuttingDown())