fix(Core/World): Remove artificially high minimal update intervals an… (#15422)
fix(Core/World): Remove artificially high minimal update intervals and Allow specifying minimum world updates diff in config * Allow specifying minimum world updates diff in config * Remove artificially high minimal update intervals * cherry-pick commit (https://github.com/TrinityCore/TrinityCore/commit/29a4153f0038526ee6df690ec3499d66630e5071) * cherry-pick commit (https://github.com/TrinityCore/TrinityCore/commit/de4920de81a495ed8d6b04cf68f3912c74921f48) * cherry-pick commit (https://github.com/jackpoz/TrinityCore/commit/32cef906b02562ffb129b095386a9314abde82f1) Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: Giacomo Pozzoni <giacomopoz@gmail.com>
This commit is contained in:
@@ -72,13 +72,15 @@ char serviceDescription[] = "AzerothCore World of Warcraft emulator world servic
|
|||||||
* 2 - paused
|
* 2 - paused
|
||||||
*/
|
*/
|
||||||
int m_ServiceStatus = -1;
|
int m_ServiceStatus = -1;
|
||||||
|
|
||||||
|
#include <boost/dll/shared_library.hpp>
|
||||||
|
#include <timeapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _ACORE_CORE_CONFIG
|
#ifndef _ACORE_CORE_CONFIG
|
||||||
#define _ACORE_CORE_CONFIG "worldserver.conf"
|
#define _ACORE_CORE_CONFIG "worldserver.conf"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WORLD_SLEEP_CONST 10
|
|
||||||
using namespace boost::program_options;
|
using namespace boost::program_options;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@@ -137,6 +139,44 @@ int main(int argc, char** argv)
|
|||||||
return WinServiceUninstall() == true ? 0 : 1;
|
return WinServiceUninstall() == true ? 0 : 1;
|
||||||
else if (configService.compare("run") == 0)
|
else if (configService.compare("run") == 0)
|
||||||
WinServiceRun();
|
WinServiceRun();
|
||||||
|
|
||||||
|
Optional<UINT> newTimerResolution;
|
||||||
|
boost::system::error_code dllError;
|
||||||
|
std::shared_ptr<boost::dll::shared_library> winmm(new boost::dll::shared_library("winmm.dll", dllError, boost::dll::load_mode::search_system_folders), [&](boost::dll::shared_library* lib)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (newTimerResolution)
|
||||||
|
lib->get<decltype(timeEndPeriod)>("timeEndPeriod")(*newTimerResolution);
|
||||||
|
}
|
||||||
|
catch (std::exception const&)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
delete lib;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (winmm->is_loaded())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto timeGetDevCapsPtr = winmm->get<decltype(timeGetDevCaps)>("timeGetDevCaps");
|
||||||
|
// setup timer resolution
|
||||||
|
TIMECAPS timeResolutionLimits;
|
||||||
|
if (timeGetDevCapsPtr(&timeResolutionLimits, sizeof(TIMECAPS)) == TIMERR_NOERROR)
|
||||||
|
{
|
||||||
|
auto timeBeginPeriodPtr = winmm->get<decltype(timeBeginPeriod)>("timeBeginPeriod");
|
||||||
|
newTimerResolution = std::min(std::max(timeResolutionLimits.wPeriodMin, 1u), timeResolutionLimits.wPeriodMax);
|
||||||
|
timeBeginPeriodPtr(*newTimerResolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
printf("Failed to initialize timer resolution: %s\n", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add file and args in config
|
// Add file and args in config
|
||||||
@@ -522,9 +562,15 @@ void ShutdownCLIThread(std::thread* cliThread)
|
|||||||
|
|
||||||
void WorldUpdateLoop()
|
void WorldUpdateLoop()
|
||||||
{
|
{
|
||||||
|
uint32 minUpdateDiff = uint32(sConfigMgr->GetOption<int32>("MinWorldUpdateTime", 1));
|
||||||
uint32 realCurrTime = 0;
|
uint32 realCurrTime = 0;
|
||||||
uint32 realPrevTime = getMSTime();
|
uint32 realPrevTime = getMSTime();
|
||||||
|
|
||||||
|
uint32 maxCoreStuckTime = uint32(sConfigMgr->GetOption<int32>("MaxCoreStuckTime", 60)) * 1000;
|
||||||
|
uint32 halfMaxCoreStuckTime = maxCoreStuckTime / 2;
|
||||||
|
if (!halfMaxCoreStuckTime)
|
||||||
|
halfMaxCoreStuckTime = std::numeric_limits<uint32>::max();
|
||||||
|
|
||||||
LoginDatabase.WarnAboutSyncQueries(true);
|
LoginDatabase.WarnAboutSyncQueries(true);
|
||||||
CharacterDatabase.WarnAboutSyncQueries(true);
|
CharacterDatabase.WarnAboutSyncQueries(true);
|
||||||
WorldDatabase.WarnAboutSyncQueries(true);
|
WorldDatabase.WarnAboutSyncQueries(true);
|
||||||
@@ -536,18 +582,19 @@ void WorldUpdateLoop()
|
|||||||
realCurrTime = getMSTime();
|
realCurrTime = getMSTime();
|
||||||
|
|
||||||
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
|
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
|
||||||
|
if (diff < minUpdateDiff)
|
||||||
|
{
|
||||||
|
uint32 sleepTime = minUpdateDiff - diff;
|
||||||
|
if (sleepTime >= halfMaxCoreStuckTime)
|
||||||
|
LOG_ERROR("server.worldserver", "WorldUpdateLoop() waiting for {} ms with MaxCoreStuckTime set to {} ms", sleepTime, maxCoreStuckTime);
|
||||||
|
// sleep until enough time passes that we can update all timers
|
||||||
|
std::this_thread::sleep_for(Milliseconds(sleepTime));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sWorld->Update(diff);
|
sWorld->Update(diff);
|
||||||
realPrevTime = realCurrTime;
|
realPrevTime = realCurrTime;
|
||||||
|
|
||||||
uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
|
|
||||||
|
|
||||||
// we know exactly how long it took to update the world, if the update took less than WORLD_SLEEP_CONST, sleep for WORLD_SLEEP_CONST - world update time
|
|
||||||
if (executionTimeDiff < WORLD_SLEEP_CONST)
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(Milliseconds(WORLD_SLEEP_CONST - executionTimeDiff));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (m_ServiceStatus == 0)
|
if (m_ServiceStatus == 0)
|
||||||
World::StopNow(SHUTDOWN_EXIT_CODE);
|
World::StopNow(SHUTDOWN_EXIT_CODE);
|
||||||
@@ -583,10 +630,14 @@ void FreezeDetector::Handler(std::weak_ptr<FreezeDetector> freezeDetectorRef, bo
|
|||||||
freezeDetector->_worldLoopCounter = worldLoopCounter;
|
freezeDetector->_worldLoopCounter = worldLoopCounter;
|
||||||
}
|
}
|
||||||
// possible freeze
|
// possible freeze
|
||||||
else if (getMSTimeDiff(freezeDetector->_lastChangeMsTime, curtime) > freezeDetector->_maxCoreStuckTimeInMs)
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR("server.worldserver", "World Thread hangs, kicking out server!");
|
uint32 msTimeDiff = getMSTimeDiff(freezeDetector->_lastChangeMsTime, curtime);
|
||||||
ABORT();
|
if (msTimeDiff > freezeDetector->_maxCoreStuckTimeInMs)
|
||||||
|
{
|
||||||
|
LOG_ERROR("server.worldserver", "World Thread hangs for {} ms, forcing a crash!", msTimeDiff);
|
||||||
|
ABORT("World Thread hangs for {} ms, forcing a crash!", msTimeDiff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freezeDetector->_timer.expires_from_now(boost::posix_time::seconds(1));
|
freezeDetector->_timer.expires_from_now(boost::posix_time::seconds(1));
|
||||||
|
|||||||
@@ -339,12 +339,19 @@ SocketTimeOutTimeActive = 60000
|
|||||||
|
|
||||||
SessionAddDelay = 10000
|
SessionAddDelay = 10000
|
||||||
|
|
||||||
|
#
|
||||||
|
# MinWorldUpdateTime
|
||||||
|
# Description: Minimum time (milliseconds) between world update ticks (for mostly idle servers).
|
||||||
|
# Default: 1 - (0.001 second)
|
||||||
|
|
||||||
|
MinWorldUpdateTime = 1
|
||||||
|
|
||||||
#
|
#
|
||||||
# MapUpdateInterval
|
# MapUpdateInterval
|
||||||
# Description: Time (milliseconds) for map update interval.
|
# Description: Time (milliseconds) for map update interval.
|
||||||
# Default: 100 - (0.1 second)
|
# Default: 10 - (0.01 second)
|
||||||
|
|
||||||
MapUpdateInterval = 100
|
MapUpdateInterval = 10
|
||||||
|
|
||||||
#
|
#
|
||||||
# ChangeWeatherInterval
|
# ChangeWeatherInterval
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class ObjectGuid;
|
|||||||
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
|
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
|
||||||
|
|
||||||
#define MIN_GRID_DELAY (MINUTE*IN_MILLISECONDS)
|
#define MIN_GRID_DELAY (MINUTE*IN_MILLISECONDS)
|
||||||
#define MIN_MAP_UPDATE_DELAY 10
|
#define MIN_MAP_UPDATE_DELAY 1
|
||||||
|
|
||||||
#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS)
|
#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS)
|
||||||
|
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
|
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 100);
|
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 10);
|
||||||
if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
|
if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
|
||||||
{
|
{
|
||||||
LOG_ERROR("server.loading", "MapUpdateInterval ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
|
LOG_ERROR("server.loading", "MapUpdateInterval ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
|
||||||
|
|||||||
@@ -141,8 +141,6 @@ enum WorldStates
|
|||||||
WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20008 // Next daily calendar deletions of old events time
|
WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20008 // Next daily calendar deletions of old events time
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WORLD_SLEEP_CONST 10
|
|
||||||
|
|
||||||
// xinef: petitions storage
|
// xinef: petitions storage
|
||||||
struct PetitionData
|
struct PetitionData
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ protected:
|
|||||||
{
|
{
|
||||||
LOG_DEBUG("misc", "Network Thread Starting");
|
LOG_DEBUG("misc", "Network Thread Starting");
|
||||||
|
|
||||||
_updateTimer.expires_from_now(boost::posix_time::milliseconds(10));
|
_updateTimer.expires_from_now(boost::posix_time::milliseconds(1));
|
||||||
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this));
|
_updateTimer.async_wait([this](boost::system::error_code const&) { Update(); });
|
||||||
_ioContext.run();
|
_ioContext.run();
|
||||||
|
|
||||||
LOG_DEBUG("misc", "Network Thread exits");
|
LOG_DEBUG("misc", "Network Thread exits");
|
||||||
@@ -135,8 +135,8 @@ protected:
|
|||||||
if (_stopped)
|
if (_stopped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_updateTimer.expires_from_now(boost::posix_time::milliseconds(10));
|
_updateTimer.expires_from_now(boost::posix_time::milliseconds(1));
|
||||||
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this));
|
_updateTimer.async_wait([this](boost::system::error_code const&) { Update(); });
|
||||||
|
|
||||||
AddNewSockets();
|
AddNewSockets();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user