aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
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/Region/Framework/Scenes/Scene.cs
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 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs94
1 files changed, 60 insertions, 34 deletions
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)