/// Heartbeat for the World
void WorldRunnable::run()
{
///- Init new SQL thread for the world database
WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough)
sWorld.InitResultQueue();
uint32 realCurrTime = 0;
uint32 realPrevTime = WorldTimer::tick();
uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST
///- While we have not World::m_stopEvent, update the world
while (!World::IsStopped())
{
++World::m_worldLoopCounter;
realCurrTime = WorldTimer::getMSTime(); //----------------(1)
uint32 diff = WorldTimer::tick(); //--------------(2)
sWorld.Update( diff ); //--------------(3)
realPrevTime = realCurrTime;
// diff (D0) include time of previous sleep (d0) + tick time (t0)
// we want that next d1 + t1 == WORLD_SLEEP_CONST
// we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement
// d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0
if (diff <= WORLD_SLEEP_CONST+prevSleepTime) //----------------(4)
{
prevSleepTime = WORLD_SLEEP_CONST+prevSleepTime-diff;
ACE_Based::Thread::Sleep(prevSleepTime);
}
else
prevSleepTime = 0;
#ifdef WIN32
if (m_ServiceStatus == 0) World::StopNow(SHUTDOWN_EXIT_CODE);
while (m_ServiceStatus == 2) Sleep(1000);
#endif
}
sWorld.KickAll(); // save and kick all players
sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call
// unload battleground templates before different singletons destroyed
sBattleGroundMgr.DeleteAllBattleGrounds();
sWorldSocketMgr->StopNetwork();
sMapMgr.UnloadAll(); // unload all grids (including locked in memory)
///- End the database thread
WorldDatabase.ThreadEnd(); // free mySQL thread resources
}
(1)从WorldTimer::getMSTime()得到一个uint32的值realCurrTime,realCurrTime是循环的(到增加到0xFFFFFFFF后,在增加就变成0),表示当前时间,单位是毫秒,是一个相对前一次tick的时间。
(2)使用WorldTimer::tick();计算上次tick到这次tick的时间差diff,该值理论上等于realCurrTime – realPrevTime
(3)sWorld.Update( diff );就是tick里的处理函数,游戏逻辑在这里得到更新处理。
(4)这里就是图1-2中的“图C”所描述的,如果运行时间大于固定的tick时间,则不sleep继续占用CPU来处理更新,直到能在一个tick处理所有操作为止,这个时候才会sleep让出CPU时间片。
(5)WORLD_SLEEP_CONST就是固定的tick的时间长度,在这里是50ms
总结:现在可以回答本节前面的两个问题:在高负荷情况下mangos采用图1-2中“图C”的方式提高服务器的响应速度,每个tick时间长度为50ms,也就是每秒钟更新20次,能满足更新的需求。