diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 702e3220f6..ae35cb9e46 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -219,6 +219,7 @@ namespace OpenSim.Region.Framework.Scenes private int backupMS; private int terrainMS; private int landMS; + private int spareMS; /// /// Tick at which the last frame was processed. @@ -1360,43 +1361,41 @@ namespace OpenSim.Region.Framework.Scenes endFrame = Frame + frames; float physicsFPS = 0f; - int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; - int previousFrameTick; - int maintc; + int previousFrameTick, tmpMS; + int maintc = Util.EnvironmentTickCount(); while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) { - maintc = Util.EnvironmentTickCount(); ++Frame; // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); - agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; + agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; try { // Apply taints in terrain module to terrain in physics scene if (Frame % m_update_terrain == 0) { - terMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); UpdateTerrain(); - terrainMS = Util.EnvironmentTickCountSubtract(terMS); + terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); } - tmpPhysicsMS2 = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); if ((Frame % m_update_physics == 0) && m_physics_enabled) m_sceneGraph.UpdatePreparePhysics(); - physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); + physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); // Apply any pending avatar force input to the avatar's velocity - tmpAgentMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); if (Frame % m_update_entitymovement == 0) m_sceneGraph.UpdateScenePresenceMovement(); - agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); + agentMS = Util.EnvironmentTickCountSubtract(tmpMS); // Perform the main physics update. This will do the actual work of moving objects and avatars according to their // velocity - tmpPhysicsMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); if (Frame % m_update_physics == 0) { if (m_physics_enabled) @@ -1405,9 +1404,9 @@ namespace OpenSim.Region.Framework.Scenes if (SynchronizeScene != null) SynchronizeScene(this); } - physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); + physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); - tmpAgentMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); // Check if any objects have reached their targets CheckAtTargets(); @@ -1422,29 +1421,29 @@ namespace OpenSim.Region.Framework.Scenes if (Frame % m_update_presences == 0) m_sceneGraph.UpdatePresences(); - agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); + agentMS += Util.EnvironmentTickCountSubtract(tmpMS); // Delete temp-on-rez stuff if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) { - tmpTempOnRezMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); m_cleaningTemps = true; Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); - tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); + tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); } if (Frame % m_update_events == 0) { - evMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); UpdateEvents(); - eventMS = Util.EnvironmentTickCountSubtract(evMS); + eventMS = Util.EnvironmentTickCountSubtract(tmpMS); } if (Frame % m_update_backup == 0) { - backMS = Util.EnvironmentTickCount(); + tmpMS = Util.EnvironmentTickCount(); UpdateStorageBackup(); - backupMS = Util.EnvironmentTickCountSubtract(backMS); + backupMS = Util.EnvironmentTickCountSubtract(tmpMS); } //if (Frame % m_update_land == 0) @@ -1453,24 +1452,6 @@ namespace OpenSim.Region.Framework.Scenes // UpdateLand(); // landMS = Util.EnvironmentTickCountSubtract(ldMS); //} - - frameMS = Util.EnvironmentTickCountSubtract(maintc); - otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; - - // if (Frame%m_update_avatars == 0) - // UpdateInWorldTime(); - StatsReporter.AddPhysicsFPS(physicsFPS); - StatsReporter.AddTimeDilation(TimeDilation); - StatsReporter.AddFPS(1); - - // frameMS currently records work frame times, not total frame times (work + any required sleep to - // reach min frame time. - StatsReporter.addFrameMS(frameMS); - - StatsReporter.addAgentMS(agentMS); - StatsReporter.addPhysicsMS(physicsMS + physicsMS2); - StatsReporter.addOtherMS(otherMS); - StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); if (LoginsDisabled && Frame == 20) { @@ -1521,13 +1502,34 @@ namespace OpenSim.Region.Framework.Scenes previousFrameTick = m_lastFrameTick; m_lastFrameTick = Util.EnvironmentTickCount(); - maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); - maintc = (int)(MinFrameTime * 1000) - maintc; + tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); + tmpMS = (int)(MinFrameTime * 1000) - tmpMS; - if (maintc > 0) - Thread.Sleep(maintc); + if (tmpMS > 0) + { + Thread.Sleep(tmpMS); + spareMS += tmpMS; + } - // Optionally warn if a frame takes double the amount of time that it should. + frameMS = Util.EnvironmentTickCountSubtract(maintc); + maintc = Util.EnvironmentTickCount(); + + otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; + + // if (Frame%m_update_avatars == 0) + // UpdateInWorldTime(); + StatsReporter.AddPhysicsFPS(physicsFPS); + StatsReporter.AddTimeDilation(TimeDilation); + StatsReporter.AddFPS(1); + + StatsReporter.addFrameMS(frameMS); + StatsReporter.addAgentMS(agentMS); + StatsReporter.addPhysicsMS(physicsMS + physicsMS2); + StatsReporter.addOtherMS(otherMS); + StatsReporter.AddSpareMS(spareMS); + StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + + // Optionally warn if a frame takes double the amount of time that it should. if (DebugUpdates && Util.EnvironmentTickCountSubtract( m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 87af311a06..742d42a7e0 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -56,10 +56,17 @@ namespace OpenSim.Region.Framework.Scenes public event YourStatsAreWrong OnStatsIncorrect; - private SendStatResult handlerSendStatResult = null; + private SendStatResult handlerSendStatResult; - private YourStatsAreWrong handlerStatsIncorrect = null; + private YourStatsAreWrong handlerStatsIncorrect; + /// + /// These are the IDs of stats sent in the StatsPacket to the viewer. + /// + /// + /// Some of these are not relevant to OpenSimulator since it is architected differently to other simulators + /// (e.g. script instructions aren't executed as part of the frame loop so 'script time' is tricky). + /// public enum Stats : uint { TimeDilation = 0, @@ -83,7 +90,20 @@ namespace OpenSim.Region.Framework.Scenes OutPacketsPerSecond = 18, PendingDownloads = 19, PendingUploads = 20, + VirtualSizeKb = 21, + ResidentSizeKb = 22, + PendingLocalUploads = 23, UnAckedBytes = 24, + PhysicsPinnedTasks = 25, + PhysicsLodTasks = 26, + SimPhysicsStepMs = 27, + SimPhysicsShapeMs = 28, + SimPhysicsOtherMs = 29, + SimPhysicsMemory = 30, + ScriptEps = 31, + SimSpareMs = 32, + SimSleepMs = 33, + SimIoPumpTime = 34 } /// @@ -117,10 +137,15 @@ namespace OpenSim.Region.Framework.Scenes private Dictionary m_lastReportedExtraSimStats = new Dictionary(); // Sending a stats update every 3 seconds- - private int statsUpdatesEveryMS = 3000; - private float statsUpdateFactor = 0; - private float m_timeDilation = 0; - private int m_fps = 0; + private int m_statsUpdatesEveryMS = 3000; + private float m_statsUpdateFactor; + private float m_timeDilation; + private int m_fps; + + /// + /// Number of the last frame on which we processed a stats udpate. + /// + private uint m_lastUpdateFrame; /// /// Our nominal fps target, as expected in fps stats when a sim is running normally. @@ -138,41 +163,42 @@ namespace OpenSim.Region.Framework.Scenes private float m_reportedFpsCorrectionFactor = 5; // saved last reported value so there is something available for llGetRegionFPS - private float lastReportedSimFPS = 0; - private float[] lastReportedSimStats = new float[21]; - private float m_pfps = 0; + private float lastReportedSimFPS; + private float[] lastReportedSimStats = new float[22]; + private float m_pfps; /// /// Number of agent updates requested in this stats cycle /// - private int m_agentUpdates = 0; + private int m_agentUpdates; /// /// Number of object updates requested in this stats cycle /// private int m_objectUpdates; - private int m_frameMS = 0; - private int m_netMS = 0; - private int m_agentMS = 0; - private int m_physicsMS = 0; - private int m_imageMS = 0; - private int m_otherMS = 0; + private int m_frameMS; + private int m_spareMS; + private int m_netMS; + private int m_agentMS; + private int m_physicsMS; + private int m_imageMS; + private int m_otherMS; //Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed. //Ckrinke private int m_scriptMS = 0; - private int m_rootAgents = 0; - private int m_childAgents = 0; - private int m_numPrim = 0; - private int m_inPacketsPerSecond = 0; - private int m_outPacketsPerSecond = 0; - private int m_activePrim = 0; - private int m_unAckedBytes = 0; - private int m_pendingDownloads = 0; - private int m_pendingUploads = 0; - private int m_activeScripts = 0; - private int m_scriptLinesPerSecond = 0; + private int m_rootAgents; + private int m_childAgents; + private int m_numPrim; + private int m_inPacketsPerSecond; + private int m_outPacketsPerSecond; + private int m_activePrim; + private int m_unAckedBytes; + private int m_pendingDownloads; + private int m_pendingUploads = 0; // FIXME: Not currently filled in + private int m_activeScripts; + private int m_scriptLinesPerSecond; private int m_objectCapacity = 45000; @@ -188,13 +214,13 @@ namespace OpenSim.Region.Framework.Scenes { m_scene = scene; m_reportedFpsCorrectionFactor = scene.MinFrameTime * m_nominalReportedFps; - statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); + m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); ReportingRegion = scene.RegionInfo; m_objectCapacity = scene.RegionInfo.ObjectCapacity; m_report.AutoReset = true; - m_report.Interval = statsUpdatesEveryMS; - m_report.Elapsed += statsHeartBeat; + m_report.Interval = m_statsUpdatesEveryMS; + m_report.Elapsed += TriggerStatsHeartbeat; m_report.Enabled = true; if (StatsManager.SimExtraStats != null) @@ -203,7 +229,7 @@ namespace OpenSim.Region.Framework.Scenes public void Close() { - m_report.Elapsed -= statsHeartBeat; + m_report.Elapsed -= TriggerStatsHeartbeat; m_report.Close(); } @@ -213,14 +239,28 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetUpdateMS(int ms) { - statsUpdatesEveryMS = ms; - statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); - m_report.Interval = statsUpdatesEveryMS; + m_statsUpdatesEveryMS = ms; + m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); + m_report.Interval = m_statsUpdatesEveryMS; + } + + private void TriggerStatsHeartbeat(object sender, EventArgs args) + { + try + { + statsHeartBeat(sender, args); + } + catch (Exception e) + { + m_log.Warn(string.Format( + "[SIM STATS REPORTER] Update for {0} failed with exception ", + m_scene.RegionInfo.RegionName), e); + } } private void statsHeartBeat(object sender, EventArgs e) { - SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21]; + SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[22]; SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); // Know what's not thread safe in Mono... modifying timers. @@ -247,7 +287,7 @@ namespace OpenSim.Region.Framework.Scenes int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); // save the reported value so there is something available for llGetRegionFPS - lastReportedSimFPS = reportedFPS / statsUpdateFactor; + lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; float physfps = ((m_pfps / 1000)); @@ -279,7 +319,15 @@ namespace OpenSim.Region.Framework.Scenes // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change // values to X-per-second values. - for (int i = 0; i < 21; i++) + uint thisFrame = m_scene.Frame; + float framesUpdated = (float)(thisFrame - m_lastUpdateFrame) * m_reportedFpsCorrectionFactor; + m_lastUpdateFrame = thisFrame; + + // Avoid div-by-zero if somehow we've not updated any frames. + if (framesUpdated == 0) + framesUpdated = 1; + + for (int i = 0; i < 22; i++) { sb[i] = new SimStatsPacket.StatBlock(); } @@ -288,13 +336,13 @@ namespace OpenSim.Region.Framework.Scenes sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); sb[1].StatID = (uint) Stats.SimFPS; - sb[1].StatValue = reportedFPS / statsUpdateFactor; + sb[1].StatValue = reportedFPS / m_statsUpdateFactor; sb[2].StatID = (uint) Stats.PhysicsFPS; - sb[2].StatValue = physfps / statsUpdateFactor; + sb[2].StatValue = physfps / m_statsUpdateFactor; sb[3].StatID = (uint) Stats.AgentUpdates; - sb[3].StatValue = (m_agentUpdates / statsUpdateFactor); + sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor); sb[4].StatID = (uint) Stats.Agents; sb[4].StatValue = m_rootAgents; @@ -309,31 +357,31 @@ namespace OpenSim.Region.Framework.Scenes sb[7].StatValue = m_activePrim; sb[8].StatID = (uint)Stats.FrameMS; - sb[8].StatValue = m_frameMS / statsUpdateFactor; + sb[8].StatValue = m_frameMS / framesUpdated; sb[9].StatID = (uint)Stats.NetMS; - sb[9].StatValue = m_netMS / statsUpdateFactor; + sb[9].StatValue = m_netMS / framesUpdated; sb[10].StatID = (uint)Stats.PhysicsMS; - sb[10].StatValue = m_physicsMS / statsUpdateFactor; + sb[10].StatValue = m_physicsMS / framesUpdated; sb[11].StatID = (uint)Stats.ImageMS ; - sb[11].StatValue = m_imageMS / statsUpdateFactor; + sb[11].StatValue = m_imageMS / framesUpdated; sb[12].StatID = (uint)Stats.OtherMS; - sb[12].StatValue = m_otherMS / statsUpdateFactor; + sb[12].StatValue = m_otherMS / framesUpdated; sb[13].StatID = (uint)Stats.InPacketsPerSecond; - sb[13].StatValue = (m_inPacketsPerSecond / statsUpdateFactor); + sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); sb[14].StatID = (uint)Stats.OutPacketsPerSecond; - sb[14].StatValue = (m_outPacketsPerSecond / statsUpdateFactor); + sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor); sb[15].StatID = (uint)Stats.UnAckedBytes; sb[15].StatValue = m_unAckedBytes; sb[16].StatID = (uint)Stats.AgentMS; - sb[16].StatValue = m_agentMS / statsUpdateFactor; + sb[16].StatValue = m_agentMS / framesUpdated; sb[17].StatID = (uint)Stats.PendingDownloads; sb[17].StatValue = m_pendingDownloads; @@ -345,9 +393,12 @@ namespace OpenSim.Region.Framework.Scenes sb[19].StatValue = m_activeScripts; sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; - sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor; - - for (int i = 0; i < 21; i++) + sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor; + + sb[21].StatID = (uint)Stats.SimSpareMs; + sb[21].StatValue = m_spareMS / framesUpdated; + + for (int i = 0; i < 22; i++) { lastReportedSimStats[i] = sb[i].StatValue; } @@ -366,7 +417,7 @@ namespace OpenSim.Region.Framework.Scenes // Extra statistics that aren't currently sent to clients lock (m_lastReportedExtraSimStats) { - m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / statsUpdateFactor; + m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; Dictionary physicsStats = m_scene.PhysicsScene.GetStats(); @@ -374,16 +425,22 @@ namespace OpenSim.Region.Framework.Scenes { foreach (KeyValuePair tuple in physicsStats) { - m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / statsUpdateFactor; + // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second + // Need to change things so that stats source can indicate whether they are per second or + // per frame. + if (tuple.Key.EndsWith("MS")) + m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated; + else + m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor; } } } - resetvalues(); + ResetValues(); } } - private void resetvalues() + private void ResetValues() { m_timeDilation = 0; m_fps = 0; @@ -401,6 +458,7 @@ namespace OpenSim.Region.Framework.Scenes m_physicsMS = 0; m_imageMS = 0; m_otherMS = 0; + m_spareMS = 0; //Ckrinke This variable is not used, so comment to remove compiler warning until it is used. //Ckrinke m_scriptMS = 0; @@ -479,6 +537,11 @@ namespace OpenSim.Region.Framework.Scenes m_frameMS += ms; } + public void AddSpareMS(int ms) + { + m_spareMS += ms; + } + public void addNetMS(int ms) { m_netMS += ms; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index deb68b83f4..fb0fdc998d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5583,7 +5583,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - List presenceIds = new List(); World.ForEachRootScenePresence( delegate (ScenePresence ssp)