Move frame loop entirely within Scene.Update() for better future performance analysis and stat accuracy.
Update() now accepts a frames parameter which can control the number of frames updated. -1 will update until shutdown. The watchdog updating moves above the maintc recalculation for any required sleep since it should be accounted for within the frame.0.7.3-extended
parent
3117b3cd88
commit
279b31c75b
|
@ -1753,6 +1753,20 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
const Int32 EnvironmentTickCountMask = 0x3fffffff;
|
const Int32 EnvironmentTickCountMask = 0x3fffffff;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
|
||||||
|
/// and negative every 24.9 days. Subtracts the passed value (previously fetched by
|
||||||
|
/// 'EnvironmentTickCount()') and accounts for any wrapping.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
/// <param name="prevValue"></param>
|
||||||
|
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
|
||||||
|
public static Int32 EnvironmentTickCountSubtract(Int32 newValue, Int32 prevValue)
|
||||||
|
{
|
||||||
|
Int32 diff = newValue - prevValue;
|
||||||
|
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
|
/// Environment.TickCount is an int but it counts all 32 bits so it goes positive
|
||||||
/// and negative every 24.9 days. Subtracts the passed value (previously fetched by
|
/// and negative every 24.9 days. Subtracts the passed value (previously fetched by
|
||||||
|
@ -1761,8 +1775,7 @@ namespace OpenSim.Framework
|
||||||
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
|
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
|
||||||
public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
|
public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
|
||||||
{
|
{
|
||||||
Int32 diff = EnvironmentTickCount() - prevValue;
|
return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
|
||||||
return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
|
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
m_regStatus = RegionStatus.Up;
|
m_regStatus = RegionStatus.Up;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update() {}
|
public override void Update(int frames) {}
|
||||||
public override void LoadWorldMap() {}
|
public override void LoadWorldMap() {}
|
||||||
|
|
||||||
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
|
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
|
||||||
|
|
|
@ -1183,11 +1183,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// The first frame can take a very long time due to physics actors being added on startup. Therefore,
|
// The first frame can take a very long time due to physics actors being added on startup. Therefore,
|
||||||
// don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
|
// don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
|
||||||
// alarms for scenes with many objects.
|
// alarms for scenes with many objects.
|
||||||
Update();
|
Update(1);
|
||||||
Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
|
Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
|
||||||
|
|
||||||
while (!shuttingdown)
|
while (!shuttingdown)
|
||||||
Update();
|
Update(-1);
|
||||||
|
|
||||||
// m_lastUpdate = Util.EnvironmentTickCount();
|
// m_lastUpdate = Util.EnvironmentTickCount();
|
||||||
// m_firstHeartbeat = false;
|
// m_firstHeartbeat = false;
|
||||||
|
@ -1201,184 +1201,205 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Watchdog.RemoveThread();
|
Watchdog.RemoveThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update(int frames)
|
||||||
{
|
{
|
||||||
|
long? endFrame = null;
|
||||||
|
|
||||||
|
if (frames >= 0)
|
||||||
|
endFrame = Frame + frames;
|
||||||
|
|
||||||
float physicsFPS = 0f;
|
float physicsFPS = 0f;
|
||||||
|
int tmpFrameMS, tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS;
|
||||||
|
int maintc;
|
||||||
|
List<Vector3> coarseLocations;
|
||||||
|
List<UUID> avatarUUIDs;
|
||||||
|
|
||||||
int maintc = Util.EnvironmentTickCount();
|
while (!shuttingdown && (endFrame == null || Frame < endFrame))
|
||||||
int tmpFrameMS = maintc;
|
{
|
||||||
agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
|
maintc = Util.EnvironmentTickCount();
|
||||||
|
++Frame;
|
||||||
++Frame;
|
|
||||||
|
|
||||||
// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
|
// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
|
||||||
|
|
||||||
try
|
tmpFrameMS = maintc;
|
||||||
{
|
agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
|
||||||
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
|
||||||
if ((Frame % m_update_physics == 0) && m_physics_enabled)
|
|
||||||
m_sceneGraph.UpdatePreparePhysics();
|
|
||||||
physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
|
|
||||||
|
|
||||||
// Apply any pending avatar force input to the avatar's velocity
|
try
|
||||||
int tmpAgentMS = Util.EnvironmentTickCount();
|
|
||||||
if (Frame % m_update_entitymovement == 0)
|
|
||||||
m_sceneGraph.UpdateScenePresenceMovement();
|
|
||||||
agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS);
|
|
||||||
|
|
||||||
// Perform the main physics update. This will do the actual work of moving objects and avatars according to their
|
|
||||||
// velocity
|
|
||||||
int tmpPhysicsMS = Util.EnvironmentTickCount();
|
|
||||||
if (Frame % m_update_physics == 0)
|
|
||||||
{
|
{
|
||||||
if (m_physics_enabled)
|
tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
||||||
physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime);
|
if ((Frame % m_update_physics == 0) && m_physics_enabled)
|
||||||
|
m_sceneGraph.UpdatePreparePhysics();
|
||||||
if (SynchronizeScene != null)
|
physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
|
||||||
SynchronizeScene(this);
|
|
||||||
}
|
// Apply any pending avatar force input to the avatar's velocity
|
||||||
physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
|
tmpAgentMS = Util.EnvironmentTickCount();
|
||||||
|
if (Frame % m_update_entitymovement == 0)
|
||||||
tmpAgentMS = Util.EnvironmentTickCount();
|
m_sceneGraph.UpdateScenePresenceMovement();
|
||||||
|
agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS);
|
||||||
// Check if any objects have reached their targets
|
|
||||||
CheckAtTargets();
|
// Perform the main physics update. This will do the actual work of moving objects and avatars according to their
|
||||||
|
// velocity
|
||||||
// Update SceneObjectGroups that have scheduled themselves for updates
|
tmpPhysicsMS = Util.EnvironmentTickCount();
|
||||||
// Objects queue their updates onto all scene presences
|
if (Frame % m_update_physics == 0)
|
||||||
if (Frame % m_update_objects == 0)
|
|
||||||
m_sceneGraph.UpdateObjectGroups();
|
|
||||||
|
|
||||||
// Run through all ScenePresences looking for updates
|
|
||||||
// Presence updates and queued object updates for each presence are sent to clients
|
|
||||||
if (Frame % m_update_presences == 0)
|
|
||||||
m_sceneGraph.UpdatePresences();
|
|
||||||
|
|
||||||
// Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
|
|
||||||
if (Frame % m_update_coarse_locations == 0)
|
|
||||||
{
|
|
||||||
List<Vector3> coarseLocations;
|
|
||||||
List<UUID> avatarUUIDs;
|
|
||||||
SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
|
|
||||||
// Send coarse locations to clients
|
|
||||||
ForEachScenePresence(delegate(ScenePresence presence)
|
|
||||||
{
|
{
|
||||||
presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
|
if (m_physics_enabled)
|
||||||
});
|
physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime);
|
||||||
}
|
|
||||||
|
if (SynchronizeScene != null)
|
||||||
agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS);
|
SynchronizeScene(this);
|
||||||
|
|
||||||
// Delete temp-on-rez stuff
|
|
||||||
if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
|
|
||||||
{
|
|
||||||
int tmpTempOnRezMS = Util.EnvironmentTickCount();
|
|
||||||
m_cleaningTemps = true;
|
|
||||||
Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
|
|
||||||
tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Frame % m_update_events == 0)
|
|
||||||
{
|
|
||||||
int evMS = Util.EnvironmentTickCount();
|
|
||||||
UpdateEvents();
|
|
||||||
eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Frame % m_update_backup == 0)
|
|
||||||
{
|
|
||||||
int backMS = Util.EnvironmentTickCount();
|
|
||||||
UpdateStorageBackup();
|
|
||||||
backupMS = Util.EnvironmentTickCountSubtract(backMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Frame % m_update_terrain == 0)
|
|
||||||
{
|
|
||||||
int terMS = Util.EnvironmentTickCount();
|
|
||||||
UpdateTerrain();
|
|
||||||
terrainMS = Util.EnvironmentTickCountSubtract(terMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (Frame % m_update_land == 0)
|
|
||||||
//{
|
|
||||||
// int ldMS = Util.EnvironmentTickCount();
|
|
||||||
// UpdateLand();
|
|
||||||
// landMS = Util.EnvironmentTickCountSubtract(ldMS);
|
|
||||||
//}
|
|
||||||
|
|
||||||
frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
|
|
||||||
otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
|
|
||||||
lastCompletedFrame = Util.EnvironmentTickCount();
|
|
||||||
|
|
||||||
// if (Frame%m_update_avatars == 0)
|
|
||||||
// UpdateInWorldTime();
|
|
||||||
StatsReporter.AddPhysicsFPS(physicsFPS);
|
|
||||||
StatsReporter.AddTimeDilation(TimeDilation);
|
|
||||||
StatsReporter.AddFPS(1);
|
|
||||||
StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
|
|
||||||
StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
|
|
||||||
StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
|
|
||||||
StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
|
|
||||||
StatsReporter.addFrameMS(frameMS);
|
|
||||||
StatsReporter.addAgentMS(agentMS);
|
|
||||||
StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
|
|
||||||
StatsReporter.addOtherMS(otherMS);
|
|
||||||
StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
|
|
||||||
StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
|
|
||||||
|
|
||||||
if (LoginsDisabled && Frame == 20)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
|
|
||||||
|
|
||||||
// In 99.9% of cases it is a bad idea to manually force garbage collection. However,
|
|
||||||
// this is a rare case where we know we have just went through a long cycle of heap
|
|
||||||
// allocations, and there is no more work to be done until someone logs in
|
|
||||||
GC.Collect();
|
|
||||||
|
|
||||||
IConfig startupConfig = m_config.Configs["Startup"];
|
|
||||||
if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
|
|
||||||
{
|
|
||||||
// This handles a case of a region having no scripts for the RegionReady module
|
|
||||||
if (m_sceneGraph.GetActiveScriptsCount() == 0)
|
|
||||||
{
|
|
||||||
// need to be able to tell these have changed in RegionReady
|
|
||||||
LoginLock = false;
|
|
||||||
EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
|
|
||||||
}
|
|
||||||
m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
|
|
||||||
|
|
||||||
// For RegionReady lockouts
|
|
||||||
if(LoginLock == false)
|
|
||||||
{
|
|
||||||
LoginsDisabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
|
|
||||||
}
|
}
|
||||||
else
|
physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
|
||||||
|
|
||||||
|
tmpAgentMS = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
|
// Check if any objects have reached their targets
|
||||||
|
CheckAtTargets();
|
||||||
|
|
||||||
|
// Update SceneObjectGroups that have scheduled themselves for updates
|
||||||
|
// Objects queue their updates onto all scene presences
|
||||||
|
if (Frame % m_update_objects == 0)
|
||||||
|
m_sceneGraph.UpdateObjectGroups();
|
||||||
|
|
||||||
|
// Run through all ScenePresences looking for updates
|
||||||
|
// Presence updates and queued object updates for each presence are sent to clients
|
||||||
|
if (Frame % m_update_presences == 0)
|
||||||
|
m_sceneGraph.UpdatePresences();
|
||||||
|
|
||||||
|
// Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
|
||||||
|
if (Frame % m_update_coarse_locations == 0)
|
||||||
{
|
{
|
||||||
StartDisabled = true;
|
SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
|
||||||
LoginsDisabled = true;
|
// Send coarse locations to clients
|
||||||
|
ForEachScenePresence(delegate(ScenePresence presence)
|
||||||
|
{
|
||||||
|
presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS);
|
||||||
|
|
||||||
|
// Delete temp-on-rez stuff
|
||||||
|
if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
|
||||||
|
{
|
||||||
|
tmpTempOnRezMS = Util.EnvironmentTickCount();
|
||||||
|
m_cleaningTemps = true;
|
||||||
|
Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
|
||||||
|
tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Frame % m_update_events == 0)
|
||||||
|
{
|
||||||
|
evMS = Util.EnvironmentTickCount();
|
||||||
|
UpdateEvents();
|
||||||
|
eventMS = Util.EnvironmentTickCountSubtract(evMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Frame % m_update_backup == 0)
|
||||||
|
{
|
||||||
|
backMS = Util.EnvironmentTickCount();
|
||||||
|
UpdateStorageBackup();
|
||||||
|
backupMS = Util.EnvironmentTickCountSubtract(backMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Frame % m_update_terrain == 0)
|
||||||
|
{
|
||||||
|
terMS = Util.EnvironmentTickCount();
|
||||||
|
UpdateTerrain();
|
||||||
|
terrainMS = Util.EnvironmentTickCountSubtract(terMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (Frame % m_update_land == 0)
|
||||||
|
//{
|
||||||
|
// int ldMS = Util.EnvironmentTickCount();
|
||||||
|
// UpdateLand();
|
||||||
|
// landMS = Util.EnvironmentTickCountSubtract(ldMS);
|
||||||
|
//}
|
||||||
|
|
||||||
|
frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
|
||||||
|
otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
|
||||||
|
lastCompletedFrame = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
|
// if (Frame%m_update_avatars == 0)
|
||||||
|
// UpdateInWorldTime();
|
||||||
|
StatsReporter.AddPhysicsFPS(physicsFPS);
|
||||||
|
StatsReporter.AddTimeDilation(TimeDilation);
|
||||||
|
StatsReporter.AddFPS(1);
|
||||||
|
StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
|
||||||
|
StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
|
||||||
|
StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
|
||||||
|
StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
|
||||||
|
|
||||||
|
// frameMS currently records work frame times, not total frame times (work + any required sleep to
|
||||||
|
// reach min frame time.
|
||||||
|
StatsReporter.addFrameMS(frameMS);
|
||||||
|
|
||||||
|
StatsReporter.addAgentMS(agentMS);
|
||||||
|
StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
|
||||||
|
StatsReporter.addOtherMS(otherMS);
|
||||||
|
StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
|
||||||
|
StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
|
||||||
|
|
||||||
|
if (LoginsDisabled && Frame == 20)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
|
||||||
|
|
||||||
|
// In 99.9% of cases it is a bad idea to manually force garbage collection. However,
|
||||||
|
// this is a rare case where we know we have just went through a long cycle of heap
|
||||||
|
// allocations, and there is no more work to be done until someone logs in
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
IConfig startupConfig = m_config.Configs["Startup"];
|
||||||
|
if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
|
||||||
|
{
|
||||||
|
// This handles a case of a region having no scripts for the RegionReady module
|
||||||
|
if (m_sceneGraph.GetActiveScriptsCount() == 0)
|
||||||
|
{
|
||||||
|
// need to be able to tell these have changed in RegionReady
|
||||||
|
LoginLock = false;
|
||||||
|
EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
|
||||||
|
|
||||||
|
// For RegionReady lockouts
|
||||||
|
if(LoginLock == false)
|
||||||
|
{
|
||||||
|
LoginsDisabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartDisabled = true;
|
||||||
|
LoginsDisabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[SCENE]: Failed on region {0} with exception {1}{2}",
|
||||||
|
RegionInfo.RegionName, e.Message, e.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventManager.TriggerRegionHeartbeatEnd(this);
|
||||||
|
|
||||||
|
// Tell the watchdog that this thread is still alive
|
||||||
|
Watchdog.UpdateThread();
|
||||||
|
|
||||||
|
maintc = Util.EnvironmentTickCountSubtract(maintc);
|
||||||
|
maintc = (int)(MinFrameTime * 1000) - maintc;
|
||||||
|
|
||||||
|
if (maintc > 0)
|
||||||
|
Thread.Sleep(maintc);
|
||||||
|
|
||||||
|
// if (frameMS > (int)(MinFrameTime * 1000))
|
||||||
|
// m_log.WarnFormat(
|
||||||
|
// "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
|
||||||
|
// frameMS,
|
||||||
|
// MinFrameTime * 1000,
|
||||||
|
// RegionInfo.RegionName);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat(
|
|
||||||
"[SCENE]: Failed on region {0} with exception {1}{2}",
|
|
||||||
RegionInfo.RegionName, e.Message, e.StackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventManager.TriggerRegionHeartbeatEnd(this);
|
|
||||||
|
|
||||||
maintc = Util.EnvironmentTickCountSubtract(maintc);
|
|
||||||
maintc = (int)(MinFrameTime * 1000) - maintc;
|
|
||||||
|
|
||||||
if (maintc > 0)
|
|
||||||
Thread.Sleep(maintc);
|
|
||||||
|
|
||||||
// Tell the watchdog that this thread is still alive
|
|
||||||
Watchdog.UpdateThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddGroupTarget(SceneObjectGroup grp)
|
public void AddGroupTarget(SceneObjectGroup grp)
|
||||||
|
|
|
@ -149,9 +149,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
#region Update Methods
|
#region Update Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Normally called once every frame/tick to let the world preform anything required (like running the physics simulation)
|
/// Called to update the scene loop by a number of frames and until shutdown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Update();
|
/// <param name="frames">
|
||||||
|
/// Number of frames to update. Exits on shutdown even if there are frames remaining.
|
||||||
|
/// If -1 then updates until shutdown.
|
||||||
|
/// </param>
|
||||||
|
public abstract void Update(int frames);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
// For now, we'll make the scene presence fly to simplify this test, but this needs to change.
|
// For now, we'll make the scene presence fly to simplify this test, but this needs to change.
|
||||||
sp.Flying = true;
|
sp.Flying = true;
|
||||||
|
|
||||||
m_scene.Update();
|
m_scene.Update(1);
|
||||||
Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos));
|
Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos));
|
||||||
|
|
||||||
Vector3 targetPos = startPos + new Vector3(0, 10, 0);
|
Vector3 targetPos = startPos + new Vector3(0, 10, 0);
|
||||||
|
@ -91,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(
|
Assert.That(
|
||||||
sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
|
sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
|
||||||
|
|
||||||
m_scene.Update();
|
m_scene.Update(1);
|
||||||
|
|
||||||
// We should really check the exact figure.
|
// We should really check the exact figure.
|
||||||
Assert.That(sp.AbsolutePosition.X, Is.EqualTo(startPos.X));
|
Assert.That(sp.AbsolutePosition.X, Is.EqualTo(startPos.X));
|
||||||
|
@ -99,8 +99,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
||||||
Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X));
|
Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X));
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
m_scene.Update(10);
|
||||||
m_scene.Update();
|
|
||||||
|
|
||||||
double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
|
double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
|
||||||
Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move");
|
Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move");
|
||||||
|
@ -116,7 +115,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(
|
Assert.That(
|
||||||
sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001));
|
sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001));
|
||||||
|
|
||||||
m_scene.Update();
|
m_scene.Update(1);
|
||||||
|
|
||||||
// We should really check the exact figure.
|
// We should really check the exact figure.
|
||||||
Assert.That(sp.AbsolutePosition.X, Is.GreaterThan(startPos.X));
|
Assert.That(sp.AbsolutePosition.X, Is.GreaterThan(startPos.X));
|
||||||
|
@ -124,8 +123,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
|
Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
|
||||||
Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
m_scene.Update(10);
|
||||||
m_scene.Update();
|
|
||||||
|
|
||||||
distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
|
distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
|
||||||
Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move");
|
Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move");
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
Scene scene = SceneHelpers.SetupScene();
|
Scene scene = SceneHelpers.SetupScene();
|
||||||
scene.Update();
|
scene.Update(1);
|
||||||
|
|
||||||
Assert.That(scene.Frame, Is.EqualTo(1));
|
Assert.That(scene.Frame, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
||||||
// For now, we'll make the scene presence fly to simplify this test, but this needs to change.
|
// For now, we'll make the scene presence fly to simplify this test, but this needs to change.
|
||||||
npc.Flying = true;
|
npc.Flying = true;
|
||||||
|
|
||||||
m_scene.Update();
|
m_scene.Update(1);
|
||||||
Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
|
Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
|
||||||
|
|
||||||
Vector3 targetPos = startPos + new Vector3(0, 10, 0);
|
Vector3 targetPos = startPos + new Vector3(0, 10, 0);
|
||||||
|
@ -249,7 +249,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
||||||
Assert.That(
|
Assert.That(
|
||||||
npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
|
npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
|
||||||
|
|
||||||
m_scene.Update();
|
m_scene.Update(1);
|
||||||
|
|
||||||
// We should really check the exact figure.
|
// We should really check the exact figure.
|
||||||
Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X));
|
Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X));
|
||||||
|
@ -257,8 +257,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
||||||
Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
||||||
Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X));
|
Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X));
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
m_scene.Update(10);
|
||||||
m_scene.Update();
|
|
||||||
|
|
||||||
double distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
|
double distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
|
||||||
Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on first move");
|
Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on first move");
|
||||||
|
@ -275,7 +274,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
||||||
Assert.That(
|
Assert.That(
|
||||||
npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001));
|
npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001));
|
||||||
|
|
||||||
m_scene.Update();
|
m_scene.Update(1);
|
||||||
|
|
||||||
// We should really check the exact figure.
|
// We should really check the exact figure.
|
||||||
Assert.That(npc.AbsolutePosition.X, Is.GreaterThan(startPos.X));
|
Assert.That(npc.AbsolutePosition.X, Is.GreaterThan(startPos.X));
|
||||||
|
@ -283,8 +282,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
||||||
Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
|
Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
|
||||||
Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
m_scene.Update(10);
|
||||||
m_scene.Update();
|
|
||||||
|
|
||||||
distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
|
distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
|
||||||
Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on second move");
|
Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on second move");
|
||||||
|
|
|
@ -154,7 +154,7 @@ namespace OpenSim.Tests.Torture
|
||||||
//
|
//
|
||||||
// However, that means that we need to manually run an update here to clear out that list so that deleted
|
// However, that means that we need to manually run an update here to clear out that list so that deleted
|
||||||
// objects will be clean up by the garbage collector before the next stress test is run.
|
// objects will be clean up by the garbage collector before the next stress test is run.
|
||||||
scene.Update();
|
scene.Update(1);
|
||||||
|
|
||||||
// Currently, we need to do this in order to garbage collect the scene objects ready for the next test run.
|
// Currently, we need to do this in order to garbage collect the scene objects ready for the next test run.
|
||||||
// However, what we really need to do is find out why the entire scene is not garbage collected in
|
// However, what we really need to do is find out why the entire scene is not garbage collected in
|
||||||
|
|
Loading…
Reference in New Issue