aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDan Lake2009-10-13 19:13:06 -0700
committerJohn Hurliman2009-10-13 19:32:59 -0700
commit5976ac16b0eedaeca2360010a3d6f7be4213700a (patch)
tree8f6a80582a4640b5be0c242fd7cf2f19db39a72a
parent* Copied LocklessQueue.cs into OpenSim.Framework and added the .Count propert... (diff)
downloadopensim-SC_OLD-5976ac16b0eedaeca2360010a3d6f7be4213700a.zip
opensim-SC_OLD-5976ac16b0eedaeca2360010a3d6f7be4213700a.tar.gz
opensim-SC_OLD-5976ac16b0eedaeca2360010a3d6f7be4213700a.tar.bz2
opensim-SC_OLD-5976ac16b0eedaeca2360010a3d6f7be4213700a.tar.xz
Optimized heartbeat by calling Update() only on updated objects.
During the heartbeat loop, Update() is called on every SceneObjectGroup which in turn checks if any SceneObjectPart has changed. For large regions (> 100k prims) this work consumes 20-30% of a CPU even though there are only a few objects updating each frame. There is only one other reason to check every object on every frame, and that is the case where a script has registered the object with an "at target" listener. We can easily track when an object is registered or unregistered with an AtTarget, so this is not a reason to check every object every heartbeat. In the attached patch, I have added a dictionary to the scene which tracks the objects which have At Targets. Each heartbeat, the AtTarget() function will be called on every object registered with a listener for that event. Also, I added a dictionary to SceneGraph which stores references to objects which have been queued for updates during the heartbeat. At each heartbeat, Update() is called only on the objects which have generated updates during that beat.
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs82
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs15
3 files changed, 52 insertions, 73 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 7944548..1ca0267 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -117,6 +117,8 @@ namespace OpenSim.Region.Framework.Scenes
117 private volatile bool m_backingup = false; 117 private volatile bool m_backingup = false;
118 118
119 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 119 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
120
121 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>();
120 122
121 protected string m_simulatorVersion = "OpenSimulator Server"; 123 protected string m_simulatorVersion = "OpenSimulator Server";
122 124
@@ -246,8 +248,7 @@ namespace OpenSim.Region.Framework.Scenes
246 248
247 private int m_update_physics = 1; 249 private int m_update_physics = 1;
248 private int m_update_entitymovement = 1; 250 private int m_update_entitymovement = 1;
249 private int m_update_entities = 1; // Run through all objects checking for updates 251 private int m_update_objects = 1; // Update objects which have scheduled themselves for updates
250 private int m_update_entitiesquick = 200; // Run through objects that have scheduled updates checking for updates
251 private int m_update_presences = 1; // Update scene presence movements 252 private int m_update_presences = 1; // Update scene presence movements
252 private int m_update_events = 1; 253 private int m_update_events = 1;
253 private int m_update_backup = 200; 254 private int m_update_backup = 200;
@@ -979,28 +980,7 @@ namespace OpenSim.Region.Framework.Scenes
979 maintc = Environment.TickCount; 980 maintc = Environment.TickCount;
980 981
981 TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; 982 TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate;
982 // Aquire a lock so only one update call happens at once
983 //updateLock.WaitOne();
984 float physicsFPS = 0; 983 float physicsFPS = 0;
985 //m_log.Info("sadfadf" + m_neighbours.Count.ToString());
986 int agentsInScene = m_sceneGraph.GetRootAgentCount() + m_sceneGraph.GetChildAgentCount();
987
988 if (agentsInScene > 21)
989 {
990 if (m_update_entities == 1)
991 {
992 m_update_entities = 5;
993 StatsReporter.SetUpdateMS(6000);
994 }
995 }
996 else
997 {
998 if (m_update_entities == 5)
999 {
1000 m_update_entities = 1;
1001 StatsReporter.SetUpdateMS(3000);
1002 }
1003 }
1004 984
1005 frameMS = Environment.TickCount; 985 frameMS = Environment.TickCount;
1006 try 986 try
@@ -1013,30 +993,17 @@ namespace OpenSim.Region.Framework.Scenes
1013 m_frame = 0; 993 m_frame = 0;
1014 994
1015 otherMS = Environment.TickCount; 995 otherMS = Environment.TickCount;
1016 // run through all entities looking for updates (slow)
1017 if (m_frame % m_update_entities == 0)
1018 {
1019 /* // Adam Experimental
1020 if (m_updateEntitiesThread == null)
1021 {
1022 m_updateEntitiesThread = new Thread(m_sceneGraph.UpdateEntities);
1023 996
1024 ThreadTracker.Add(m_updateEntitiesThread); 997 // Check if any objects have reached their targets
1025 } 998 CheckAtTargets();
1026 999
1027 if (m_updateEntitiesThread.ThreadState == ThreadState.Stopped) 1000 // Update SceneObjectGroups that have scheduled themselves for updates
1028 m_updateEntitiesThread.Start(); 1001 // Objects queue their updates onto all scene presences
1029 */ 1002 if (m_frame % m_update_objects == 0)
1030 1003 m_sceneGraph.UpdateObjectGroups();
1031 m_sceneGraph.UpdateEntities();
1032 }
1033 1004
1034 // run through entities that have scheduled themselves for 1005 // Run through all ScenePresences looking for updates
1035 // updates looking for updates(faster) 1006 // Presence updates and queued object updates for each presence are sent to clients
1036 if (m_frame % m_update_entitiesquick == 0)
1037 m_sceneGraph.ProcessUpdates();
1038
1039 // Run through scenepresences looking for updates
1040 if (m_frame % m_update_presences == 0) 1007 if (m_frame % m_update_presences == 0)
1041 m_sceneGraph.UpdatePresences(); 1008 m_sceneGraph.UpdatePresences();
1042 1009
@@ -1140,6 +1107,31 @@ namespace OpenSim.Region.Framework.Scenes
1140 } 1107 }
1141 } 1108 }
1142 1109
1110
1111 public void AddGroupTarget(SceneObjectGroup grp)
1112 {
1113 lock(m_groupsWithTargets)
1114 m_groupsWithTargets[grp.UUID] = grp;
1115 }
1116
1117 public void RemoveGroupTarget(SceneObjectGroup grp)
1118 {
1119 lock(m_groupsWithTargets)
1120 m_groupsWithTargets.Remove(grp.UUID);
1121 }
1122
1123 private void CheckAtTargets()
1124 {
1125 lock (m_groupsWithTargets)
1126 {
1127 foreach (KeyValuePair<UUID, SceneObjectGroup> kvp in m_groupsWithTargets)
1128 {
1129 kvp.Value.checkAtTargets();
1130 }
1131 }
1132 }
1133
1134
1143 /// <summary> 1135 /// <summary>
1144 /// Send out simstats data to all clients 1136 /// Send out simstats data to all clients
1145 /// </summary> 1137 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 54ac792..9cd2247 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
77 77
78 protected RegionInfo m_regInfo; 78 protected RegionInfo m_regInfo;
79 protected Scene m_parentScene; 79 protected Scene m_parentScene;
80 protected Dictionary<UUID, EntityBase> m_updateList = new Dictionary<UUID, EntityBase>(); 80 protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
81 protected int m_numRootAgents = 0; 81 protected int m_numRootAgents = 0;
82 protected int m_numPrim = 0; 82 protected int m_numPrim = 0;
83 protected int m_numChildAgents = 0; 83 protected int m_numChildAgents = 0;
@@ -155,16 +155,6 @@ namespace OpenSim.Region.Framework.Scenes
155 } 155 }
156 } 156 }
157 157
158 protected internal void UpdateEntities()
159 {
160 List<EntityBase> updateEntities = GetEntities();
161
162 foreach (EntityBase entity in updateEntities)
163 {
164 entity.Update();
165 }
166 }
167
168 protected internal void UpdatePresences() 158 protected internal void UpdatePresences()
169 { 159 {
170 List<ScenePresence> updateScenePresences = GetScenePresences(); 160 List<ScenePresence> updateScenePresences = GetScenePresences();
@@ -365,12 +355,12 @@ namespace OpenSim.Region.Framework.Scenes
365 } 355 }
366 356
367 /// <summary> 357 /// <summary>
368 /// Add an entity to the list of prims to process on the next update 358 /// Add an object to the list of prims to process on the next update
369 /// </summary> 359 /// </summary>
370 /// <param name="obj"> 360 /// <param name="obj">
371 /// A <see cref="EntityBase"/> 361 /// A <see cref="SceneObjectGroup"/>
372 /// </param> 362 /// </param>
373 protected internal void AddToUpdateList(EntityBase obj) 363 protected internal void AddToUpdateList(SceneObjectGroup obj)
374 { 364 {
375 lock (m_updateList) 365 lock (m_updateList)
376 { 366 {
@@ -381,18 +371,18 @@ namespace OpenSim.Region.Framework.Scenes
381 /// <summary> 371 /// <summary>
382 /// Process all pending updates 372 /// Process all pending updates
383 /// </summary> 373 /// </summary>
384 protected internal void ProcessUpdates() 374 protected internal void UpdateObjectGroups()
385 { 375 {
386 Dictionary<UUID, EntityBase> updates; 376 Dictionary<UUID, SceneObjectGroup> updates;
387 // Some updates add more updates to the updateList. 377 // Some updates add more updates to the updateList.
388 // Get the current list of updates and clear the list before iterating 378 // Get the current list of updates and clear the list before iterating
389 lock (m_updateList) 379 lock (m_updateList)
390 { 380 {
391 updates = new Dictionary<UUID, EntityBase>(m_updateList); 381 updates = new Dictionary<UUID, SceneObjectGroup>(m_updateList);
392 m_updateList.Clear(); 382 m_updateList.Clear();
393 } 383 }
394 // Go through all timers 384 // Go through all updates
395 foreach (KeyValuePair<UUID, EntityBase> kvp in updates) 385 foreach (KeyValuePair<UUID, SceneObjectGroup> kvp in updates)
396 { 386 {
397 // Don't abort the whole update if one entity happens to give us an exception. 387 // Don't abort the whole update if one entity happens to give us an exception.
398 try 388 try
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6a10618..d4cef7d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1234,6 +1234,7 @@ namespace OpenSim.Region.Framework.Scenes
1234 { 1234 {
1235 lock (m_targets) 1235 lock (m_targets)
1236 m_targets.Clear(); 1236 m_targets.Clear();
1237 m_scene.RemoveGroupTarget(this);
1237 } 1238 }
1238 1239
1239 ScheduleGroupForFullUpdate(); 1240 ScheduleGroupForFullUpdate();
@@ -1864,12 +1865,6 @@ namespace OpenSim.Region.Framework.Scenes
1864 m_rootPart.UpdateFlag = 1; 1865 m_rootPart.UpdateFlag = 1;
1865 lastPhysGroupPos = AbsolutePosition; 1866 lastPhysGroupPos = AbsolutePosition;
1866 } 1867 }
1867 //foreach (SceneObjectPart part in m_parts.Values)
1868 //{
1869 //if (part.UpdateFlag == 0) part.UpdateFlag = 1;
1870 //}
1871
1872 checkAtTargets();
1873 1868
1874 if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) 1869 if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
1875 || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) 1870 || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
@@ -3114,6 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
3114 { 3109 {
3115 m_targets.Add(handle, waypoint); 3110 m_targets.Add(handle, waypoint);
3116 } 3111 }
3112 m_scene.AddGroupTarget(this);
3117 return (int)handle; 3113 return (int)handle;
3118 } 3114 }
3119 3115
@@ -3121,12 +3117,13 @@ namespace OpenSim.Region.Framework.Scenes
3121 { 3117 {
3122 lock (m_targets) 3118 lock (m_targets)
3123 { 3119 {
3124 if (m_targets.ContainsKey((uint)handle)) 3120 m_targets.Remove((uint)handle);
3125 m_targets.Remove((uint)handle); 3121 if (m_targets.Count == 0)
3122 m_scene.RemoveGroupTarget(this);
3126 } 3123 }
3127 } 3124 }
3128 3125
3129 private void checkAtTargets() 3126 public void checkAtTargets()
3130 { 3127 {
3131 if (m_scriptListens_atTarget || m_scriptListens_notAtTarget) 3128 if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
3132 { 3129 {