* Removed Heartbeat timer

* Implemented a proper update thread
* Removed the UpdateLock Mutex as it's no longer needed because updates can only happen one at a time now.
* This should actually improve performance significantly.. But, see the warning on the next line!
* Warning: If there are deadlocks that the threadpool timer method was hiding, this will expose them for all the nastiness they are.
0.6.0-stable
Teravus Ovares 2008-10-11 11:43:42 +00:00
parent dd5746fb8a
commit abc6424c51
1 changed files with 162 additions and 141 deletions

View File

@ -61,9 +61,10 @@ namespace OpenSim.Region.Environment.Scenes
public SynchronizeSceneHandler SynchronizeScene = null; public SynchronizeSceneHandler SynchronizeScene = null;
public int splitID = 0; public int splitID = 0;
#region Fields #region Fields
protected Timer m_heartbeatTimer = new Timer();
protected Timer m_restartWaitTimer = new Timer(); protected Timer m_restartWaitTimer = new Timer();
protected SimStatsReporter m_statsReporter; protected SimStatsReporter m_statsReporter;
@ -83,7 +84,7 @@ namespace OpenSim.Region.Environment.Scenes
private int m_timePhase = 24; private int m_timePhase = 24;
private readonly Mutex updateLock;
/// <summary> /// <summary>
/// Are we applying physics to any of the prims in this scene? /// Are we applying physics to any of the prims in this scene?
@ -169,6 +170,8 @@ namespace OpenSim.Region.Environment.Scenes
private bool m_scripts_enabled = true; private bool m_scripts_enabled = true;
private string m_defaultScriptEngine; private string m_defaultScriptEngine;
private int m_LastLogin = 0; private int m_LastLogin = 0;
private Thread HeartbeatThread;
private volatile bool shuttingdown = false;
#endregion #endregion
@ -259,7 +262,7 @@ namespace OpenSim.Region.Environment.Scenes
bool SeeIntoRegionFromNeighbor, IConfigSource config, string simulatorVersion) bool SeeIntoRegionFromNeighbor, IConfigSource config, string simulatorVersion)
{ {
m_config = config; m_config = config;
updateLock = new Mutex(false);
m_moduleLoader = moduleLoader; m_moduleLoader = moduleLoader;
m_authenticateHandler = authen; m_authenticateHandler = authen;
CommsManager = commsMan; CommsManager = commsMan;
@ -631,7 +634,8 @@ namespace OpenSim.Region.Environment.Scenes
// Stop all client threads. // Stop all client threads.
ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); }); ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); });
// Stop updating the scene objects and agents. // Stop updating the scene objects and agents.
m_heartbeatTimer.Close(); //m_heartbeatTimer.Close();
shuttingdown = true;
// close the inner scene // close the inner scene
m_innerScene.Close(); m_innerScene.Close();
// De-register with region communications (events cleanup) // De-register with region communications (events cleanup)
@ -656,10 +660,16 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
public void StartTimer() public void StartTimer()
{ {
m_log.Debug("[SCENE]: Starting timer"); //m_log.Debug("[SCENE]: Starting timer");
m_heartbeatTimer.Enabled = true; //m_heartbeatTimer.Enabled = true;
m_heartbeatTimer.Interval = (int)(m_timespan * 1000); //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
HeartbeatThread = new Thread(new ParameterizedThreadStart(Heartbeat));
HeartbeatThread.SetApartmentState(ApartmentState.MTA);
HeartbeatThread.Name = "Heartbeat";
HeartbeatThread.Priority = ThreadPriority.AboveNormal;
ThreadTracker.Add(HeartbeatThread);
HeartbeatThread.Start();
} }
/// <summary> /// <summary>
@ -685,7 +695,7 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
private void Heartbeat(object sender, EventArgs e) private void Heartbeat(object sender)
{ {
Update(); Update();
} }
@ -695,146 +705,157 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
public override void Update() public override void Update()
{ {
TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; int maintc = 0;
// Aquire a lock so only one update call happens at once while (!shuttingdown)
updateLock.WaitOne();
float physicsFPS = 0;
//m_log.Info("sadfadf" + m_neighbours.Count.ToString());
int agentsInScene = m_innerScene.GetRootAgentCount() + m_innerScene.GetChildAgentCount();
if (agentsInScene > 21)
{ {
if (m_update_entities == 1) maintc = System.Environment.TickCount;
TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate;
// Aquire a lock so only one update call happens at once
//updateLock.WaitOne();
float physicsFPS = 0;
//m_log.Info("sadfadf" + m_neighbours.Count.ToString());
int agentsInScene = m_innerScene.GetRootAgentCount() + m_innerScene.GetChildAgentCount();
if (agentsInScene > 21)
{ {
m_update_entities = 5; if (m_update_entities == 1)
m_statsReporter.SetUpdateMS(6000);
}
}
else
{
if (m_update_entities == 5)
{
m_update_entities = 1;
m_statsReporter.SetUpdateMS(3000);
}
}
frameMS = System.Environment.TickCount;
try
{
// Increment the frame counter
m_frame++;
// Loop it
if (m_frame == Int32.MaxValue)
m_frame = 0;
physicsMS2 = System.Environment.TickCount;
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
m_innerScene.UpdatePreparePhysics();
physicsMS2 = System.Environment.TickCount - physicsMS2;
if (m_frame % m_update_entitymovement == 0)
m_innerScene.UpdateEntityMovement();
physicsMS = System.Environment.TickCount;
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
physicsFPS = m_innerScene.UpdatePhysics(
Math.Max(SinceLastFrame.TotalSeconds, m_timespan)
);
if (m_frame % m_update_physics == 0 && SynchronizeScene != null)
SynchronizeScene(this);
physicsMS = System.Environment.TickCount - physicsMS;
physicsMS += physicsMS2;
otherMS = System.Environment.TickCount;
// run through all entities looking for updates (slow)
if (m_frame % m_update_entities == 0)
m_innerScene.UpdateEntities();
// run through entities that have scheduled themselves for
// updates looking for updates(faster)
if (m_frame % m_update_entitiesquick == 0)
m_innerScene.ProcessUpdates();
// Run through scenepresences looking for updates
if (m_frame % m_update_presences == 0)
m_innerScene.UpdatePresences();
// Delete temp-on-rez stuff
if (m_frame % m_update_backup == 0)
CleanTempObjects();
if (Region_Status != RegionStatus.SlaveScene)
{
if (m_frame % m_update_events == 0)
UpdateEvents();
if (m_frame % m_update_backup == 0)
{ {
UpdateStorageBackup(); m_update_entities = 5;
m_statsReporter.SetUpdateMS(6000);
} }
if (m_frame % m_update_terrain == 0)
UpdateTerrain();
if (m_frame % m_update_land == 0)
UpdateLand();
otherMS = System.Environment.TickCount - otherMS;
// if (m_frame%m_update_avatars == 0)
// UpdateInWorldTime();
m_statsReporter.AddPhysicsFPS(physicsFPS);
m_statsReporter.AddTimeDilation(m_timedilation);
m_statsReporter.AddFPS(1);
m_statsReporter.AddInPackets(0);
m_statsReporter.SetRootAgents(m_innerScene.GetRootAgentCount());
m_statsReporter.SetChildAgents(m_innerScene.GetChildAgentCount());
m_statsReporter.SetObjects(m_innerScene.GetTotalObjectsCount());
m_statsReporter.SetActiveObjects(m_innerScene.GetActiveObjectsCount());
frameMS = System.Environment.TickCount - frameMS;
m_statsReporter.addFrameMS(frameMS);
m_statsReporter.addPhysicsMS(physicsMS);
m_statsReporter.addOtherMS(otherMS);
m_statsReporter.SetActiveScripts(m_innerScene.GetActiveScriptsCount());
m_statsReporter.addScriptLines(m_innerScene.GetScriptLPS());
} }
} else
catch (NotImplementedException)
{
throw;
}
catch (AccessViolationException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (NullReferenceException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (InvalidOperationException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (Exception e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
finally
{
updateLock.ReleaseMutex();
// Get actual time dilation
float tmpval = (m_timespan / (float)SinceLastFrame.TotalSeconds);
// If actual time dilation is greater then one, we're catching up, so subtract
// the amount that's greater then 1 from the time dilation
if (tmpval > 1.0)
{ {
tmpval = tmpval - (tmpval - 1.0f); if (m_update_entities == 5)
{
m_update_entities = 1;
m_statsReporter.SetUpdateMS(3000);
}
} }
m_timedilation = tmpval;
m_lastupdate = DateTime.Now; frameMS = System.Environment.TickCount;
try
{
// Increment the frame counter
m_frame++;
// Loop it
if (m_frame == Int32.MaxValue)
m_frame = 0;
physicsMS2 = System.Environment.TickCount;
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
m_innerScene.UpdatePreparePhysics();
physicsMS2 = System.Environment.TickCount - physicsMS2;
if (m_frame % m_update_entitymovement == 0)
m_innerScene.UpdateEntityMovement();
physicsMS = System.Environment.TickCount;
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
physicsFPS = m_innerScene.UpdatePhysics(
Math.Max(SinceLastFrame.TotalSeconds, m_timespan)
);
if (m_frame % m_update_physics == 0 && SynchronizeScene != null)
SynchronizeScene(this);
physicsMS = System.Environment.TickCount - physicsMS;
physicsMS += physicsMS2;
otherMS = System.Environment.TickCount;
// run through all entities looking for updates (slow)
if (m_frame % m_update_entities == 0)
m_innerScene.UpdateEntities();
// run through entities that have scheduled themselves for
// updates looking for updates(faster)
if (m_frame % m_update_entitiesquick == 0)
m_innerScene.ProcessUpdates();
// Run through scenepresences looking for updates
if (m_frame % m_update_presences == 0)
m_innerScene.UpdatePresences();
// Delete temp-on-rez stuff
if (m_frame % m_update_backup == 0)
CleanTempObjects();
if (Region_Status != RegionStatus.SlaveScene)
{
if (m_frame % m_update_events == 0)
UpdateEvents();
if (m_frame % m_update_backup == 0)
{
UpdateStorageBackup();
}
if (m_frame % m_update_terrain == 0)
UpdateTerrain();
if (m_frame % m_update_land == 0)
UpdateLand();
otherMS = System.Environment.TickCount - otherMS;
// if (m_frame%m_update_avatars == 0)
// UpdateInWorldTime();
m_statsReporter.AddPhysicsFPS(physicsFPS);
m_statsReporter.AddTimeDilation(m_timedilation);
m_statsReporter.AddFPS(1);
m_statsReporter.AddInPackets(0);
m_statsReporter.SetRootAgents(m_innerScene.GetRootAgentCount());
m_statsReporter.SetChildAgents(m_innerScene.GetChildAgentCount());
m_statsReporter.SetObjects(m_innerScene.GetTotalObjectsCount());
m_statsReporter.SetActiveObjects(m_innerScene.GetActiveObjectsCount());
frameMS = System.Environment.TickCount - frameMS;
m_statsReporter.addFrameMS(frameMS);
m_statsReporter.addPhysicsMS(physicsMS);
m_statsReporter.addOtherMS(otherMS);
m_statsReporter.SetActiveScripts(m_innerScene.GetActiveScriptsCount());
m_statsReporter.addScriptLines(m_innerScene.GetScriptLPS());
}
}
catch (NotImplementedException)
{
throw;
}
catch (AccessViolationException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (NullReferenceException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (InvalidOperationException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (Exception e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
finally
{
//updateLock.ReleaseMutex();
// Get actual time dilation
float tmpval = (m_timespan / (float)SinceLastFrame.TotalSeconds);
// If actual time dilation is greater then one, we're catching up, so subtract
// the amount that's greater then 1 from the time dilation
if (tmpval > 1.0)
{
tmpval = tmpval - (tmpval - 1.0f);
}
m_timedilation = tmpval;
m_lastupdate = DateTime.Now;
}
maintc = System.Environment.TickCount - maintc;
maintc = (int)(m_timespan * 1000) - maintc;
if ((maintc < (m_timespan * 1000)) && maintc > 0)
Thread.Sleep(maintc);
} }
} }