aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-03-23 02:49:29 +0000
committerJustin Clark-Casey (justincc)2012-03-23 02:49:29 +0000
commit4ed833bc9dba8e0208777f8afde32a67aebe143a (patch)
tree431062b455ce62f98ae36ed4887b53c756d69cab
parentRemove unnecessary shutting down check in Scene.Heartbeat(). Add some method... (diff)
downloadopensim-SC_OLD-4ed833bc9dba8e0208777f8afde32a67aebe143a.zip
opensim-SC_OLD-4ed833bc9dba8e0208777f8afde32a67aebe143a.tar.gz
opensim-SC_OLD-4ed833bc9dba8e0208777f8afde32a67aebe143a.tar.bz2
opensim-SC_OLD-4ed833bc9dba8e0208777f8afde32a67aebe143a.tar.xz
Add a scene maintenance thread in parallel to the heartbeat thread. The maintenance thread will end up running regular jobs that don't need to be in the main scene loop.
The idea is to make the critical main scene loop as skinny as possible - it doesn't need to run things that aren't time critical and don't depend on update ordering. This will be done gradually over time to try and uncover any issues. Many non-criticial scene loop activities are being launched on separate threadpool threads anyway. This may also allow modules to register their own maintenance jobs without having to maintain their own timers and threads. Currently the maintenance loop runs once a second, as opposed to the 89ms scene loop.
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs91
1 files changed, 77 insertions, 14 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 09b91c0..41e9bbc 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -169,6 +169,11 @@ namespace OpenSim.Region.Framework.Scenes
169 } 169 }
170 170
171 /// <summary> 171 /// <summary>
172 /// Current maintenance run number
173 /// </summary>
174 public uint MaintenanceRun { get; private set; }
175
176 /// <summary>
172 /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we 177 /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we
173 /// will sleep for the remaining period. 178 /// will sleep for the remaining period.
174 /// </summary> 179 /// </summary>
@@ -178,6 +183,11 @@ namespace OpenSim.Region.Framework.Scenes
178 /// </remarks> 183 /// </remarks>
179 public float MinFrameTime { get; private set; } 184 public float MinFrameTime { get; private set; }
180 185
186 /// <summary>
187 /// The minimum length of time in seconds that will be taken for a maintenance run.
188 /// </summary>
189 public float MinMaintenanceTime { get; private set; }
190
181 private int m_update_physics = 1; 191 private int m_update_physics = 1;
182 private int m_update_entitymovement = 1; 192 private int m_update_entitymovement = 1;
183 private int m_update_objects = 1; 193 private int m_update_objects = 1;
@@ -206,6 +216,11 @@ namespace OpenSim.Region.Framework.Scenes
206 private int m_lastFrameTick; 216 private int m_lastFrameTick;
207 217
208 /// <summary> 218 /// <summary>
219 /// Tick at which the last maintenance run occurred.
220 /// </summary>
221 private int m_lastMaintenanceTick;
222
223 /// <summary>
209 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 224 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
210 /// asynchronously from the update loop. 225 /// asynchronously from the update loop.
211 /// </summary> 226 /// </summary>
@@ -560,6 +575,7 @@ namespace OpenSim.Region.Framework.Scenes
560 { 575 {
561 m_config = config; 576 m_config = config;
562 MinFrameTime = 0.089f; 577 MinFrameTime = 0.089f;
578 MinMaintenanceTime = 1;
563 579
564 Random random = new Random(); 580 Random random = new Random();
565 581
@@ -1226,6 +1242,10 @@ namespace OpenSim.Region.Framework.Scenes
1226 // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false 1242 // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
1227 // alarms for scenes with many objects. 1243 // alarms for scenes with many objects.
1228 Update(1); 1244 Update(1);
1245
1246 Watchdog.StartThread(
1247 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1248
1229 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1249 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1230 Update(-1); 1250 Update(-1);
1231 1251
@@ -1241,6 +1261,63 @@ namespace OpenSim.Region.Framework.Scenes
1241 Watchdog.RemoveThread(); 1261 Watchdog.RemoveThread();
1242 } 1262 }
1243 1263
1264 private void Maintenance()
1265 {
1266 DoMaintenance(-1);
1267
1268 Watchdog.RemoveThread();
1269 }
1270
1271 public void DoMaintenance(int runs)
1272 {
1273 long? endRun = null;
1274 int runtc;
1275 int previousMaintenanceTick;
1276
1277 if (runs >= 0)
1278 endRun = MaintenanceRun + runs;
1279
1280 List<Vector3> coarseLocations;
1281 List<UUID> avatarUUIDs;
1282
1283 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun))
1284 {
1285 runtc = Util.EnvironmentTickCount();
1286 ++MaintenanceRun;
1287
1288 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1289 if (MaintenanceRun % (m_update_coarse_locations / 10) == 0)
1290 {
1291 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1292 // Send coarse locations to clients
1293 ForEachScenePresence(delegate(ScenePresence presence)
1294 {
1295 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1296 });
1297 }
1298
1299 Watchdog.UpdateThread();
1300
1301 previousMaintenanceTick = m_lastMaintenanceTick;
1302 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1303 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1304 runtc = (int)(MinMaintenanceTime * 1000) - runtc;
1305
1306 if (runtc > 0)
1307 Thread.Sleep(runtc);
1308
1309 // Optionally warn if a frame takes double the amount of time that it should.
1310 if (DebugUpdates
1311 && Util.EnvironmentTickCountSubtract(
1312 m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2))
1313 m_log.WarnFormat(
1314 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1315 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1316 MinMaintenanceTime * 1000,
1317 RegionInfo.RegionName);
1318 }
1319 }
1320
1244 public override void Update(int frames) 1321 public override void Update(int frames)
1245 { 1322 {
1246 long? endFrame = null; 1323 long? endFrame = null;
@@ -1252,8 +1329,6 @@ namespace OpenSim.Region.Framework.Scenes
1252 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; 1329 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS;
1253 int previousFrameTick; 1330 int previousFrameTick;
1254 int maintc; 1331 int maintc;
1255 List<Vector3> coarseLocations;
1256 List<UUID> avatarUUIDs;
1257 1332
1258 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1333 while (!m_shuttingDown && (endFrame == null || Frame < endFrame))
1259 { 1334 {
@@ -1305,17 +1380,6 @@ namespace OpenSim.Region.Framework.Scenes
1305 if (Frame % m_update_presences == 0) 1380 if (Frame % m_update_presences == 0)
1306 m_sceneGraph.UpdatePresences(); 1381 m_sceneGraph.UpdatePresences();
1307 1382
1308 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1309 if (Frame % m_update_coarse_locations == 0)
1310 {
1311 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1312 // Send coarse locations to clients
1313 ForEachScenePresence(delegate(ScenePresence presence)
1314 {
1315 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1316 });
1317 }
1318
1319 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); 1383 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS);
1320 1384
1321 // Delete temp-on-rez stuff 1385 // Delete temp-on-rez stuff
@@ -1423,7 +1487,6 @@ namespace OpenSim.Region.Framework.Scenes
1423 1487
1424 EventManager.TriggerRegionHeartbeatEnd(this); 1488 EventManager.TriggerRegionHeartbeatEnd(this);
1425 1489
1426 // Tell the watchdog that this thread is still alive
1427 Watchdog.UpdateThread(); 1490 Watchdog.UpdateThread();
1428 1491
1429 previousFrameTick = m_lastFrameTick; 1492 previousFrameTick = m_lastFrameTick;