aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2014-08-26 17:37:18 +0100
committerJustin Clark-Casey (justincc)2014-08-26 18:13:38 +0100
commit64f640f9019b0ecc65e1e2038acde306db425ebb (patch)
tree1eac847cc2579eabc52255ff55e1c9a9817b4637 /OpenSim
parentAdd back URL endings in examples (diff)
downloadopensim-SC-64f640f9019b0ecc65e1e2038acde306db425ebb.zip
opensim-SC-64f640f9019b0ecc65e1e2038acde306db425ebb.tar.gz
opensim-SC-64f640f9019b0ecc65e1e2038acde306db425ebb.tar.bz2
opensim-SC-64f640f9019b0ecc65e1e2038acde306db425ebb.tar.xz
Implement experimental non-default mechanism to update scene via a timer rather than a persistent thread with sleep.
This is to see if an inaccuracy in sleep times under load is responsible for increase in frame times even when there is spare time still available. Can currently only be activated by setting "debug scene set update-on-timer true". Can be switched between timer and thread with sleep updates whilst the scene is running.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs94
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs3
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs81
4 files changed, 113 insertions, 67 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
index e2178e5..39d1875 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
49 m_regStatus = RegionStatus.Up; 49 m_regStatus = RegionStatus.Up;
50 } 50 }
51 51
52 public override void Update(int frames) {} 52 public override bool Update(int frames) { return true; }
53 public override void LoadWorldMap() {} 53 public override void LoadWorldMap() {}
54 54
55 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) 55 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index a43de29..53001e9 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -329,6 +329,17 @@ namespace OpenSim.Region.Framework.Scenes
329 private Dictionary<string, string> m_extraSettings; 329 private Dictionary<string, string> m_extraSettings;
330 330
331 /// <summary> 331 /// <summary>
332 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
333 /// rather than on a single thread that sleeps.
334 /// </summary>
335 public bool UpdateOnTimer { get; set; }
336
337 /// <summary>
338 /// Only used if we are updating scene on a timer rather than sleeping a thread.
339 /// </summary>
340 private Timer m_sceneUpdateTimer;
341
342 /// <summary>
332 /// Current scene frame number 343 /// Current scene frame number
333 /// </summary> 344 /// </summary>
334 public uint Frame 345 public uint Frame
@@ -430,7 +441,8 @@ namespace OpenSim.Region.Framework.Scenes
430 /// Is the scene active? 441 /// Is the scene active?
431 /// </summary> 442 /// </summary>
432 /// <remarks> 443 /// <remarks>
433 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if 444 /// If false, maintenance and update loops are not being run, though after setting to false update may still
445 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if
434 /// the scene is not active. 446 /// the scene is not active.
435 /// </remarks> 447 /// </remarks>
436 public bool Active 448 public bool Active
@@ -453,8 +465,11 @@ namespace OpenSim.Region.Framework.Scenes
453 } 465 }
454 private volatile bool m_active; 466 private volatile bool m_active;
455 467
456// private int m_lastUpdate; 468 /// <summary>
457// private bool m_firstHeartbeat = true; 469 /// If true then updates are running. This may be true for a short period after a scene is de-activated.
470 /// </summary>
471 public bool IsRunning { get { return m_isRunning; } }
472 private volatile bool m_isRunning;
458 473
459 private Timer m_mapGenerationTimer = new Timer(); 474 private Timer m_mapGenerationTimer = new Timer();
460 private bool m_generateMaptiles; 475 private bool m_generateMaptiles;
@@ -1352,19 +1367,18 @@ namespace OpenSim.Region.Framework.Scenes
1352 /// </param> 1367 /// </param>
1353 public void Start(bool startScripts) 1368 public void Start(bool startScripts)
1354 { 1369 {
1370 if (IsRunning)
1371 return;
1372
1373 m_isRunning = true;
1355 m_active = true; 1374 m_active = true;
1356 1375
1357// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1376// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1358
1359 //m_heartbeatTimer.Enabled = true;
1360 //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
1361 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1362 if (m_heartbeatThread != null) 1377 if (m_heartbeatThread != null)
1363 { 1378 {
1364 m_heartbeatThread.Abort(); 1379 m_heartbeatThread.Abort();
1365 m_heartbeatThread = null; 1380 m_heartbeatThread = null;
1366 } 1381 }
1367// m_lastUpdate = Util.EnvironmentTickCount();
1368 1382
1369 m_heartbeatThread 1383 m_heartbeatThread
1370 = Watchdog.StartThread( 1384 = Watchdog.StartThread(
@@ -1401,15 +1415,6 @@ namespace OpenSim.Region.Framework.Scenes
1401 /// </summary> 1415 /// </summary>
1402 private void Heartbeat() 1416 private void Heartbeat()
1403 { 1417 {
1404// if (!Monitor.TryEnter(m_heartbeatLock))
1405// {
1406// Watchdog.RemoveThread();
1407// return;
1408// }
1409
1410// try
1411// {
1412
1413 m_eventManager.TriggerOnRegionStarted(this); 1418 m_eventManager.TriggerOnRegionStarted(this);
1414 1419
1415 // The first frame can take a very long time due to physics actors being added on startup. Therefore, 1420 // The first frame can take a very long time due to physics actors being added on startup. Therefore,
@@ -1418,21 +1423,37 @@ namespace OpenSim.Region.Framework.Scenes
1418 Update(1); 1423 Update(1);
1419 1424
1420 Watchdog.StartThread( 1425 Watchdog.StartThread(
1421 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); 1426 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1422 1427
1423 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1428 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1424 Update(-1);
1425 1429
1426// m_lastUpdate = Util.EnvironmentTickCount(); 1430 if (UpdateOnTimer)
1427// m_firstHeartbeat = false; 1431 {
1428// } 1432 m_sceneUpdateTimer = new Timer(MinFrameTime * 1000);
1429// finally 1433 m_sceneUpdateTimer.AutoReset = true;
1430// { 1434 m_sceneUpdateTimer.Elapsed += Update;
1431// Monitor.Pulse(m_heartbeatLock); 1435 m_sceneUpdateTimer.Start();
1432// Monitor.Exit(m_heartbeatLock); 1436 }
1433// } 1437 else
1438 {
1439 Update(-1);
1440 Watchdog.RemoveThread();
1441 m_isRunning = false;
1442 }
1443 }
1434 1444
1435 Watchdog.RemoveThread(); 1445 private void Update(object sender, ElapsedEventArgs e)
1446 {
1447 // If the last frame did not complete on time, then immediately start the next update on the same thread
1448 // and ignore further timed updates until we have a frame that had spare time.
1449 while (!Update(1) && Active) {}
1450
1451 if (!Active || m_shuttingDown)
1452 {
1453 m_sceneUpdateTimer.Stop();
1454 m_sceneUpdateTimer = null;
1455 m_isRunning = false;
1456 }
1436 } 1457 }
1437 1458
1438 private void Maintenance() 1459 private void Maintenance()
@@ -1502,7 +1523,7 @@ namespace OpenSim.Region.Framework.Scenes
1502 } 1523 }
1503 } 1524 }
1504 1525
1505 public override void Update(int frames) 1526 public override bool Update(int frames)
1506 { 1527 {
1507 long? endFrame = null; 1528 long? endFrame = null;
1508 1529
@@ -1652,7 +1673,8 @@ namespace OpenSim.Region.Framework.Scenes
1652 1673
1653 EventManager.TriggerRegionHeartbeatEnd(this); 1674 EventManager.TriggerRegionHeartbeatEnd(this);
1654 1675
1655 Watchdog.UpdateThread(); 1676 if (!UpdateOnTimer)
1677 Watchdog.UpdateThread();
1656 1678
1657 previousFrameTick = m_lastFrameTick; 1679 previousFrameTick = m_lastFrameTick;
1658 m_lastFrameTick = Util.EnvironmentTickCount(); 1680 m_lastFrameTick = Util.EnvironmentTickCount();
@@ -1661,9 +1683,11 @@ namespace OpenSim.Region.Framework.Scenes
1661 1683
1662 if (tmpMS > 0) 1684 if (tmpMS > 0)
1663 { 1685 {
1664 Thread.Sleep(tmpMS); 1686 spareMS = tmpMS;
1665 spareMS += tmpMS; 1687
1666 } 1688 if (!UpdateOnTimer)
1689 Thread.Sleep(tmpMS);
1690 }
1667 1691
1668 frameMS = Util.EnvironmentTickCountSubtract(maintc); 1692 frameMS = Util.EnvironmentTickCountSubtract(maintc);
1669 maintc = Util.EnvironmentTickCount(); 1693 maintc = Util.EnvironmentTickCount();
@@ -1683,7 +1707,7 @@ namespace OpenSim.Region.Framework.Scenes
1683 StatsReporter.AddSpareMS(spareMS); 1707 StatsReporter.AddSpareMS(spareMS);
1684 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); 1708 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1685 1709
1686 // Optionally warn if a frame takes double the amount of time that it should. 1710 // Optionally warn if a frame takes double the amount of time that it should.
1687 if (DebugUpdates 1711 if (DebugUpdates
1688 && Util.EnvironmentTickCountSubtract( 1712 && Util.EnvironmentTickCountSubtract(
1689 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) 1713 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2))
@@ -1693,6 +1717,8 @@ namespace OpenSim.Region.Framework.Scenes
1693 MinFrameTime * 1000, 1717 MinFrameTime * 1000,
1694 RegionInfo.RegionName); 1718 RegionInfo.RegionName);
1695 } 1719 }
1720
1721 return spareMS >= 0;
1696 } 1722 }
1697 1723
1698 public void AddGroupTarget(SceneObjectGroup grp) 1724 public void AddGroupTarget(SceneObjectGroup grp)
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 0445268..aaddce6 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -196,7 +196,8 @@ namespace OpenSim.Region.Framework.Scenes
196 /// Number of frames to update. Exits on shutdown even if there are frames remaining. 196 /// Number of frames to update. Exits on shutdown even if there are frames remaining.
197 /// If -1 then updates until shutdown. 197 /// If -1 then updates until shutdown.
198 /// </param> 198 /// </param>
199 public abstract void Update(int frames); 199 /// <returns>true if update completed within minimum frame time, false otherwise.</returns>
200 public abstract bool Update(int frames);
200 201
201 #endregion 202 #endregion
202 203
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index f2595c8..0927c4f 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Threading;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
@@ -93,42 +94,44 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
93 "Debug", this, "debug scene get", 94 "Debug", this, "debug scene get",
94 "debug scene get", 95 "debug scene get",
95 "List current scene options.", 96 "List current scene options.",
96 "active - if false then main scene update and maintenance loops are suspended.\n" 97 "active - if false then main scene update and maintenance loops are suspended.\n"
97 + "animations - if true then extra animations debug information is logged.\n" 98 + "animations - if true then extra animations debug information is logged.\n"
98 + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" 99 + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n"
99 + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" 100 + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n"
100 + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" 101 + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
101 + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" 102 + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
102 + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" 103 + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n"
103 + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" 104 + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n"
104 + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" 105 + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n"
105 + "collisions - if false then collisions with other objects are turned off.\n" 106 + "collisions - if false then collisions with other objects are turned off.\n"
106 + "pbackup - if false then periodic scene backup is turned off.\n" 107 + "pbackup - if false then periodic scene backup is turned off.\n"
107 + "physics - if false then all physics objects are non-physical.\n" 108 + "physics - if false then all physics objects are non-physical.\n"
108 + "scripting - if false then no scripting operations happen.\n" 109 + "scripting - if false then no scripting operations happen.\n"
109 + "teleport - if true then some extra teleport debug information is logged.\n" 110 + "teleport - if true then some extra teleport debug information is logged.\n"
110 + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", 111 + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n"
112 + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.",
111 HandleDebugSceneGetCommand); 113 HandleDebugSceneGetCommand);
112 114
113 scene.AddCommand( 115 scene.AddCommand(
114 "Debug", this, "debug scene set", 116 "Debug", this, "debug scene set",
115 "debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false", 117 "debug scene set <param> <value>",
116 "Turn on scene debugging options.", 118 "Turn on scene debugging options.",
117 "active - if false then main scene update and maintenance loops are suspended.\n" 119 "active - if false then main scene update and maintenance loops are suspended.\n"
118 + "animations - if true then extra animations debug information is logged.\n" 120 + "animations - if true then extra animations debug information is logged.\n"
119 + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" 121 + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n"
120 + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" 122 + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n"
121 + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" 123 + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
122 + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" 124 + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n"
123 + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" 125 + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n"
124 + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" 126 + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n"
125 + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" 127 + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n"
126 + "collisions - if false then collisions with other objects are turned off.\n" 128 + "collisions - if false then collisions with other objects are turned off.\n"
127 + "pbackup - if false then periodic scene backup is turned off.\n" 129 + "pbackup - if false then periodic scene backup is turned off.\n"
128 + "physics - if false then all physics objects are non-physical.\n" 130 + "physics - if false then all physics objects are non-physical.\n"
129 + "scripting - if false then no scripting operations happen.\n" 131 + "scripting - if false then no scripting operations happen.\n"
130 + "teleport - if true then some extra teleport debug information is logged.\n" 132 + "teleport - if true then some extra teleport debug information is logged.\n"
131 + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", 133 + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n"
134 + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.",
132 HandleDebugSceneSetCommand); 135 HandleDebugSceneSetCommand);
133 } 136 }
134 137
@@ -163,6 +166,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
163 cdl.AddRow("physics", m_scene.PhysicsEnabled); 166 cdl.AddRow("physics", m_scene.PhysicsEnabled);
164 cdl.AddRow("scripting", m_scene.ScriptsEnabled); 167 cdl.AddRow("scripting", m_scene.ScriptsEnabled);
165 cdl.AddRow("teleport", m_scene.DebugTeleporting); 168 cdl.AddRow("teleport", m_scene.DebugTeleporting);
169 cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer);
166 cdl.AddRow("updates", m_scene.DebugUpdates); 170 cdl.AddRow("updates", m_scene.DebugUpdates);
167 171
168 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); 172 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name);
@@ -304,6 +308,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
304 m_scene.DebugTeleporting = enableTeleportDebugging; 308 m_scene.DebugTeleporting = enableTeleportDebugging;
305 } 309 }
306 310
311 if (options.ContainsKey("update-on-timer"))
312 {
313 bool enableUpdateOnTimer;
314 if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer))
315 {
316 m_scene.UpdateOnTimer = enableUpdateOnTimer;
317 m_scene.Active = false;
318
319 while (m_scene.IsRunning)
320 Thread.Sleep(20);
321
322 m_scene.Active = true;
323 }
324 }
325
307 if (options.ContainsKey("updates")) 326 if (options.ContainsKey("updates"))
308 { 327 {
309 bool enableUpdateDebugging; 328 bool enableUpdateDebugging;