From 59eb378d16fd8a9e887560a2744cc798fef08263 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Wed, 28 Oct 2009 23:10:16 -0700 Subject: [PATCH] Small performance tweaks to code called by the heartbeat loop --- OpenSim/Region/Framework/Scenes/Scene.cs | 60 ++++++-------- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 14 ++-- .../Framework/Scenes/SceneObjectGroup.cs | 17 +--- .../Region/Framework/Scenes/ScenePresence.cs | 79 ++++--------------- 4 files changed, 53 insertions(+), 117 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8b0431cb3f..78ccb55690 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -257,7 +257,7 @@ namespace OpenSim.Region.Framework.Scenes // Central Update Loop protected int m_fps = 10; - protected int m_frame; + protected uint m_frame; protected float m_timespan = 0.089f; protected DateTime m_lastupdate = DateTime.UtcNow; @@ -1018,36 +1018,24 @@ namespace OpenSim.Region.Framework.Scenes /// public override void Update() { - int maintc = 0; + float physicsFPS; + int maintc; + while (!shuttingdown) { -//#if DEBUG -// int w = 0, io = 0; -// ThreadPool.GetAvailableThreads(out w, out io); -// if ((w < 10) || (io < 10)) -// m_log.DebugFormat("[WARNING]: ThreadPool reaching exhaustion. workers = {0}; io = {1}", w, io); -//#endif - maintc = Environment.TickCount; - TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate; - float physicsFPS = 0; + physicsFPS = 0f; - frameMS = Environment.TickCount; + maintc = maintc = frameMS = otherMS = Environment.TickCount; + + // Increment the frame counter + ++m_frame; try { - // Increment the frame counter - m_frame++; - - // Loop it - if (m_frame == Int32.MaxValue) - m_frame = 0; - - otherMS = Environment.TickCount; - // 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 (m_frame % m_update_objects == 0) @@ -1067,13 +1055,13 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGraph.UpdateScenePresenceMovement(); physicsMS = Environment.TickCount; - if ((m_frame % m_update_physics == 0) && m_physics_enabled) - physicsFPS = m_sceneGraph.UpdatePhysics( - Math.Max(SinceLastFrame.TotalSeconds, m_timespan) - ); - if (m_frame % m_update_physics == 0 && SynchronizeScene != null) - SynchronizeScene(this); - + if (m_frame % m_update_physics == 0) + { + if (m_physics_enabled) + physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan)); + if (SynchronizeScene != null) + SynchronizeScene(this); + } physicsMS = Environment.TickCount - physicsMS; physicsMS += physicsMS2; @@ -1095,25 +1083,27 @@ namespace OpenSim.Region.Framework.Scenes if (m_frame % m_update_land == 0) UpdateLand(); - otherMS = Environment.TickCount - otherMS; + int tickCount = Environment.TickCount; + otherMS = tickCount - otherMS; + frameMS = tickCount - frameMS; + // if (m_frame%m_update_avatars == 0) // UpdateInWorldTime(); StatsReporter.AddPhysicsFPS(physicsFPS); StatsReporter.AddTimeDilation(TimeDilation); StatsReporter.AddFPS(1); - StatsReporter.AddInPackets(0); StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); - frameMS = Environment.TickCount - frameMS; StatsReporter.addFrameMS(frameMS); StatsReporter.addPhysicsMS(physicsMS); StatsReporter.addOtherMS(otherMS); StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); } - if (loginsdisabled && (m_frame > 20)) + + if (loginsdisabled && m_frame > 20) { // 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 @@ -1176,9 +1166,9 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_groupsWithTargets) { - foreach (KeyValuePair kvp in m_groupsWithTargets) + foreach (SceneObjectGroup entry in m_groupsWithTargets.Values) { - kvp.Value.checkAtTargets(); + entry.checkAtTargets(); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index db055f968e..2fdb48dd89 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -369,26 +369,30 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void UpdateObjectGroups() { - Dictionary updates; + List updates; + // Some updates add more updates to the updateList. // Get the current list of updates and clear the list before iterating lock (m_updateList) { - updates = new Dictionary(m_updateList); + updates = new List(m_updateList.Values); m_updateList.Clear(); } + // Go through all updates - foreach (KeyValuePair kvp in updates) + for (int i = 0; i < updates.Count; i++) { + SceneObjectGroup sog = updates[i]; + // Don't abort the whole update if one entity happens to give us an exception. try { - kvp.Value.Update(); + sog.Update(); } catch (Exception e) { m_log.ErrorFormat( - "[INNER SCENE]: Failed to update {0}, {1} - {2}", kvp.Value.Name, kvp.Value.UUID, e); + "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index dbb06f8115..0b752c967a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1857,28 +1857,15 @@ namespace OpenSim.Region.Framework.Scenes { bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); - //if (IsAttachment) - //{ - //foreach (SceneObjectPart part in m_parts.Values) - //{ - //part.SendScheduledUpdates(); - //} - //return; - //} - - if (UsePhysics && Util.DistanceLessThan(lastPhysGroupPos, AbsolutePosition, 0.02)) + if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) { m_rootPart.UpdateFlag = 1; lastPhysGroupPos = AbsolutePosition; } - if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) - || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) - || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1) - || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1))) + if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) { m_rootPart.UpdateFlag = 1; - lastPhysGroupRot = GroupRotation; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 63c979f43d..1ea4585907 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -76,8 +76,7 @@ namespace OpenSim.Region.Framework.Scenes private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; - - public static byte[] DefaultTexture; + public static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); public UUID currentParcelUUID = UUID.Zero; @@ -100,9 +99,9 @@ namespace OpenSim.Region.Framework.Scenes private bool m_updateflag; private byte m_movementflag; - private readonly List m_forcesList = new List(); + private Vector3? m_forceToApply; private uint m_requestedSitTargetID; - private UUID m_requestedSitTargetUUID = UUID.Zero; + private UUID m_requestedSitTargetUUID; private SendCourseLocationsMethod m_sendCourseLocationsMethod; private bool m_startAnimationSet; @@ -456,12 +455,9 @@ namespace OpenSim.Region.Framework.Scenes { get { - if (m_physicsActor != null) - { - m_velocity.X = m_physicsActor.Velocity.X; - m_velocity.Y = m_physicsActor.Velocity.Y; - m_velocity.Z = m_physicsActor.Velocity.Z; - } + PhysicsActor actor = m_physicsActor; + if (actor != null) + m_velocity = m_physicsActor.Velocity; return m_velocity; } @@ -2278,7 +2274,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_isChildAgent) { - m_log.Debug("DEBUG: AddNewMovement: child agent, Making root agent!"); + m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); // we have to reset the user's child agent connections. // Likely, here they've lost the eventqueue for other regions so border @@ -2287,7 +2283,7 @@ namespace OpenSim.Region.Framework.Scenes List regions = new List(KnownChildRegionHandles); regions.Remove(m_scene.RegionInfo.RegionHandle); - MakeRootAgent(new Vector3(127, 127, 127), true); + MakeRootAgent(new Vector3(127f, 127f, 127f), true); // Async command if (m_scene.SceneGridService != null) @@ -2299,28 +2295,24 @@ namespace OpenSim.Region.Framework.Scenes System.Threading.Thread.Sleep(500); } - if (m_scene.SceneGridService != null) { m_scene.SceneGridService.EnableNeighbourChildAgents(this, new List()); } - - return; } m_perfMonMS = Environment.TickCount; m_rotation = rotation; - NewForce newVelocity = new NewForce(); Vector3 direc = vec * rotation; direc.Normalize(); direc *= 0.03f * 128f * m_speedModifier; if (m_physicsActor.Flying) { - direc *= 4; + direc *= 4.0f; //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); //bool colliding = (m_physicsActor.IsColliding==true); //if (controlland) @@ -2348,10 +2340,8 @@ namespace OpenSim.Region.Framework.Scenes } } - newVelocity.X = direc.X; - newVelocity.Y = direc.Y; - newVelocity.Z = direc.Z; - m_forcesList.Add(newVelocity); + // TODO: Add the force instead of only setting it to support multiple forces per frame? + m_forceToApply = direc; m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS); } @@ -3298,47 +3288,18 @@ namespace OpenSim.Region.Framework.Scenes /// public override void UpdateMovement() { - lock (m_forcesList) + if (m_forceToApply.HasValue) { - if (m_forcesList.Count > 0) - { - //we are only interested in the last velocity added to the list [Although they are called forces, they are actually velocities] - NewForce force = m_forcesList[m_forcesList.Count - 1]; + Vector3 force = m_forceToApply.Value; - m_updateflag = true; - try - { - movementvector.X = force.X; - movementvector.Y = force.Y; - movementvector.Z = force.Z; - Velocity = movementvector; - } - catch (NullReferenceException) - { - // Under extreme load, this returns a NullReference Exception that we can ignore. - // Ignoring this causes no movement to be sent to the physics engine... - // which when the scene is moving at 1 frame every 10 seconds, it doesn't really matter! - } + m_updateflag = true; + movementvector = force; + Velocity = force; - m_forcesList.Clear(); - } + m_forceToApply = null; } } - static ScenePresence() - { - Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); - DefaultTexture = textu.GetBytes(); - - } - - public class NewForce - { - public float X; - public float Y; - public float Z; - } - public override void SetText(string text, Vector3 color, double alpha) { throw new Exception("Can't set Text on avatar."); @@ -3349,7 +3310,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddToPhysicalScene(bool isFlying) { - PhysicsScene scene = m_scene.PhysicsScene; Vector3 pVec = AbsolutePosition; @@ -3478,11 +3438,6 @@ namespace OpenSim.Region.Framework.Scenes public ScenePresence() { - if (DefaultTexture == null) - { - Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); - DefaultTexture = textu.GetBytes(); - } m_sendCourseLocationsMethod = SendCoarseLocationsDefault; CreateSceneViewer(); }