From 1959eb8372b6c8e35e1afa435504e9ef41dec958 Mon Sep 17 00:00:00 2001 From: Glenn Martin Date: Mon, 20 Apr 2015 14:55:00 -0400 Subject: [PATCH] Moved over metrics from previous OpenSim 0.8.0.3 repository (this new repository is now the master branch from OpenSim). --- .../Monitoring/SimExtraStatsCollector.cs | 47 ++++ OpenSim/Region/Framework/Scenes/Scene.cs | 108 ++++++++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 59 ++++- .../Framework/Scenes/SimStatsReporter.cs | 216 ++++++++++++++++-- .../Region/ScriptEngine/XEngine/XEngine.cs | 36 +++ bin/OpenSimDefaults.ini | 2 +- 6 files changed, 449 insertions(+), 19 deletions(-) mode change 100644 => 100755 OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/Scene.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SceneGraph.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SimStatsReporter.cs mode change 100644 => 100755 OpenSim/Region/ScriptEngine/XEngine/XEngine.cs mode change 100644 => 100755 bin/OpenSimDefaults.ini diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs old mode 100644 new mode 100755 index f6f458d3ec..98fa65a297 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using OpenMetaverse; @@ -71,6 +72,10 @@ namespace OpenSim.Framework.Monitoring private volatile float pendingUploads; private volatile float activeScripts; private volatile float scriptLinesPerSecond; + private volatile float m_usersLoggingIn; + private volatile float m_totalGeoPrims; + private volatile float m_totalMeshes; + private volatile float m_inUseThreads; // /// // /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the @@ -249,6 +254,10 @@ namespace OpenSim.Framework.Monitoring { // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original // SimStatsPacket that was being used). + + // For an unknown reason the original designers decided not to + // include the spare MS statistic inside of this class, this is + // located inside the StatsBlock at location 21 thus it is skipped timeDilation = stats.StatsBlock[0].StatValue; simFps = stats.StatsBlock[1].StatValue; physicsFps = stats.StatsBlock[2].StatValue; @@ -270,6 +279,10 @@ namespace OpenSim.Framework.Monitoring pendingUploads = stats.StatsBlock[18].StatValue; activeScripts = stats.StatsBlock[19].StatValue; scriptLinesPerSecond = stats.StatsBlock[20].StatValue; + m_usersLoggingIn = stats.StatsBlock[22].StatValue; + m_totalGeoPrims = stats.StatsBlock[23].StatValue; + m_totalMeshes = stats.StatsBlock[24].StatValue; + m_inUseThreads = stats.StatsBlock[25].StatValue; } /// @@ -407,6 +420,23 @@ Asset service request failures: {3}" + Environment.NewLine, /// public override OSDMap OReport(string uptime, string version) { + // Get the amount of physical memory, allocated with the instance of this program, in kilobytes; + // the working set is the set of memory pages currently visible to this program in physical RAM + // memory and includes both shared (e.g. system libraries) and private data + double memUsage = Process.GetCurrentProcess().WorkingSet64 / 1024.0; + + // Get the number of threads from the system that are currently + // running + int numberThreadsRunning = 0; + foreach (ProcessThread currentThread in + Process.GetCurrentProcess().Threads) + { + if (currentThread.ThreadState == ThreadState.Running) + { + numberThreadsRunning++; + } + } + OSDMap args = new OSDMap(30); // args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); // args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", @@ -443,6 +473,23 @@ Asset service request failures: {3}" + Environment.NewLine, args["Memory"] = OSD.FromString (base.XReport (uptime, version)); args["Uptime"] = OSD.FromString (uptime); args["Version"] = OSD.FromString (version); + + args["Logging in Users"] = OSD.FromString(String.Format("{0:0.##}", + m_usersLoggingIn)); + args["GeoPrims"] = OSD.FromString(String.Format("{0:0.##}", + m_totalGeoPrims)); + args["Mesh Objects"] = OSD.FromString(String.Format("{0:0.##}", + m_totalMeshes)); + args["Polygon Count"] = OSD.FromString(String.Format("{0:0.##}", 0)); + args["Texture Count"] = OSD.FromString(String.Format("{0:0.##}", 0)); + args["XEngine Thread Count"] = OSD.FromString(String.Format("{0:0.##}", + m_inUseThreads)); + args["Util Thread Count"] = OSD.FromString(String.Format("{0:0.##}", + Util.GetSmartThreadPoolInfo().InUseThreads)); + args["System Thread Count"] = OSD.FromString(String.Format( + "{0:0.##}", numberThreadsRunning)); + args["ProcMem"] = OSD.FromString(String.Format("{0:#,###,###.##}", + memUsage)); return args; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs old mode 100644 new mode 100755 index 471555877b..052567fb93 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -526,6 +526,13 @@ namespace OpenSim.Region.Framework.Scenes get { return m_sceneGraph.PhysicsScene.TimeDilation; } } + public void setThreadCount(int inUseThreads) + { + // Just pass the thread count information on its way as the Scene + // does not require the value for anything at this time + StatsReporter.SetThreadCount(inUseThreads); + } + public SceneCommunicationService SceneGridService { get { return m_sceneGridService; } @@ -1107,7 +1114,35 @@ namespace OpenSim.Region.Framework.Scenes #endregion Interest Management - StatsReporter = new SimStatsReporter(this); + // The timer used by the Stopwatch class depends on the system hardware and operating system; inform + // if the timer is based on a high-resolution performance counter or based on the system timer; + // the performance counter will provide a more precise time than the system timer + if (Stopwatch.IsHighResolution) + m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics."); + else + m_log.InfoFormat("[SCENE]: Using system timer for statistics."); + + // Acquire the statistics section of the OpenSim.ini file located + // in the bin directory + IConfig statisticsConfig = m_config.Configs["Statistics"]; + + // Confirm that the statistics section existed in the configuration + // file + if (statisticsConfig != null) + { + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", 10)); + } + else + { + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); + } + StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; @@ -1607,6 +1642,21 @@ namespace OpenSim.Region.Framework.Scenes float physicsFPS = 0f; int previousFrameTick, tmpMS; + // These variables will be used to save the precise frame time using the + // Stopwatch class of Microsoft SDK; the times are recorded at the start + // and end of a parcticular section of code, and then used to calculate + // the frame times, which are the sums of the sections for each given name + double preciseTotalFrameTime = 0.0; + double preciseSimFrameTime = 0.0; + double precisePhysicsFrameTime = 0.0; + Stopwatch totalFrameStopwatch = new Stopwatch(); + Stopwatch simFrameStopwatch = new Stopwatch(); + Stopwatch physicsFrameStopwatch = new Stopwatch(); + + // Begin the stopwatch to keep track of the time that the frame + // started running to determine how long the frame took to complete + totalFrameStopwatch.Start(); + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { ++Frame; @@ -1627,20 +1677,47 @@ namespace OpenSim.Region.Framework.Scenes terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); } + // At several points inside the code there was a need to + // create a more precise measurement of time elapsed. This + // led to the addition of variables that have a similar + // function and thus remain tightly connected to their + // original counterparts. However, the original code is + // not receiving comments from our group because we don't + // feel right modifying the code to that degree at this + // point in time, the precise values all begin with the + // keyword precise + tmpMS = Util.EnvironmentTickCount(); + + // Begin the stopwatch to track the time to prepare physics + physicsFrameStopwatch.Start(); if (PhysicsEnabled && Frame % m_update_physics == 0) m_sceneGraph.UpdatePreparePhysics(); + + // Get the time it took to prepare the physics, this + // would report the most precise time that physics was + // running on the machine and should the physics not be + // enabled will report the time it took to check if physics + // was enabled + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); // Apply any pending avatar force input to the avatar's velocity tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Start(); if (Frame % m_update_entitymovement == 0) m_sceneGraph.UpdateScenePresenceMovement(); + + // Get the simulation frame time that the avatar force input took + simFrameStopwatch.Stop(); + preciseSimFrameTime = simFrameStopwatch.Elapsed.TotalMilliseconds; agentMS = Util.EnvironmentTickCountSubtract(tmpMS); // Perform the main physics update. This will do the actual work of moving objects and avatars according to their // velocity tmpMS = Util.EnvironmentTickCount(); + physicsFrameStopwatch.Restart(); if (Frame % m_update_physics == 0) { if (PhysicsEnabled) @@ -1649,8 +1726,14 @@ namespace OpenSim.Region.Framework.Scenes if (SynchronizeScene != null) SynchronizeScene(this); } + + // Add the main physics update time to the prepare physics time + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); + // Start the stopwatch for the remainder of the simulation + simFrameStopwatch.Restart(); tmpMS = Util.EnvironmentTickCount(); // Check if any objects have reached their targets @@ -1754,6 +1837,10 @@ namespace OpenSim.Region.Framework.Scenes spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); } + // Get the elapsed time for the simulation frame + simFrameStopwatch.Stop(); + preciseSimFrameTime += simFrameStopwatch.Elapsed.TotalMilliseconds; + previousFrameTick = m_lastFrameTick; frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); m_lastFrameTick = Util.EnvironmentTickCount(); @@ -1771,6 +1858,15 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.AddSpareMS(spareMS); StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + // Send the correct time values to the stats reporter for the + // frame times + StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, + preciseSimFrameTime, precisePhysicsFrameTime, 0.0); + + // Send the correct number of frames that the physics library + // has processed to the stats reporter + StatsReporter.addPhysicsFrame(1); + // Optionally warn if a frame takes double the amount of time that it should. if (DebugUpdates && Util.EnvironmentTickCountSubtract( @@ -1782,6 +1878,9 @@ namespace OpenSim.Region.Framework.Scenes RegionInfo.RegionName); } + // Finished updating scene frame, so stop the total frame's Stopwatch + totalFrameStopwatch.Stop(); + return spareMS >= 0; } @@ -2702,6 +2801,9 @@ namespace OpenSim.Region.Framework.Scenes bool vialogin; bool reallyNew = true; + // Update the number of users attempting to login + StatsReporter.UpdateUsersLoggingIn(true); + // Validation occurs in LLUDPServer // // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with @@ -2786,6 +2888,10 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnClientLogin(client); } + // User has logged into the scene so update the list of users logging + // in + StatsReporter.UpdateUsersLoggingIn(false); + m_LastLogin = Util.EnvironmentTickCount(); return sp; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs old mode 100644 new mode 100755 index 51f50d9ea8..c2e9b61ea8 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -67,7 +67,9 @@ namespace OpenSim.Region.Framework.Scenes protected Scene m_parentScene; protected Dictionary m_updateList = new Dictionary(); protected int m_numRootAgents = 0; + protected int m_numTotalPrim = 0; protected int m_numPrim = 0; + protected int m_numMesh = 0; protected int m_numChildAgents = 0; protected int m_physicalPrim = 0; @@ -368,7 +370,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = sceneObject.Parts; - // Clamp child prim sizes and add child prims to the m_numPrim count + // Clamp the sizes (scales) of the child prims and add the child prims to the count of all primitives + // (meshes and geometric primitives) in the scene; add child prims to m_numTotalPrim count if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in parts) @@ -382,7 +385,19 @@ namespace OpenSim.Region.Framework.Scenes part.Shape.Scale = scale; } } - m_numPrim += parts.Length; + m_numTotalPrim += parts.Length; + + // Go through all parts (geometric primitives and meshes) of this Scene Object + foreach (SceneObjectPart part in parts) + { + // Keep track of the total number of meshes or geometric primitives now in the scene; + // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to + // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh++; + else + m_numPrim++; + } sceneObject.AttachToScene(m_parentScene); @@ -437,7 +452,21 @@ namespace OpenSim.Region.Framework.Scenes if (!resultOfObjectLinked) { - m_numPrim -= grp.PrimCount; + // Decrement the total number of primitives (meshes and geometric primitives) + // that are part of the Scene Object being removed + m_numTotalPrim -= grp.PrimCount; + + // Go through all parts (primitives and meshes) of this Scene Object + foreach (SceneObjectPart part in grp.Parts) + { + // Keep track of the total number of meshes or geometric primitives left in the scene; + // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to + // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh--; + else + m_numPrim--; + } if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) RemovePhysicalPrim(grp.PrimCount); @@ -686,10 +715,20 @@ namespace OpenSim.Region.Framework.Scenes } public int GetTotalObjectsCount() + { + return m_numTotalPrim; + } + + public int GetTotalPrimObjectsCount() { return m_numPrim; } + public int GetTotalMeshObjectsCount() + { + return m_numMesh; + } + public int GetActiveObjectsCount() { return m_physicalPrim; @@ -1970,7 +2009,19 @@ namespace OpenSim.Region.Framework.Scenes // think it's selected, so it will never send a deselect... copy.IsSelected = false; - m_numPrim += copy.Parts.Length; + m_numTotalPrim += copy.Parts.Length; + + // Go through all parts (primitives and meshes) of this Scene Object + foreach (SceneObjectPart part in copy.Parts) + { + // Keep track of the total number of meshes or geometric primitives now in the scene; + // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to + // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh++; + else + m_numPrim++; + } if (rot != Quaternion.Identity) { diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs old mode 100644 new mode 100755 index 8f1e3456dd..b6da6364d6 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -61,6 +61,10 @@ namespace OpenSim.Region.Framework.Scenes private YourStatsAreWrong handlerStatsIncorrect; + // Determines the size of the array that is used to collect StatBlocks + // for sending to the SimStats and SimExtraStatsCollector + private const int m_statisticArraySize = 26; + /// /// These are the IDs of stats sent in the StatsPacket to the viewer. /// @@ -104,7 +108,11 @@ namespace OpenSim.Region.Framework.Scenes ScriptEps = 31, SimSpareMs = 32, SimSleepMs = 33, - SimIoPumpTime = 34 + SimIoPumpTime = 34, + UsersLoggingIn = 35, + TotalGeoPrim = 36, + TotalMesh = 37, + ThreadCount = 38 } /// @@ -175,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes // saved last reported value so there is something available for llGetRegionFPS private float lastReportedSimFPS; - private float[] lastReportedSimStats = new float[22]; + private float[] lastReportedSimStats = new float[m_statisticArraySize]; private float m_pfps; /// @@ -202,6 +210,8 @@ namespace OpenSim.Region.Framework.Scenes private int m_rootAgents; private int m_childAgents; private int m_numPrim; + private int m_numGeoPrim; + private int m_numMesh; private int m_inPacketsPerSecond; private int m_outPacketsPerSecond; private int m_activePrim; @@ -213,6 +223,34 @@ namespace OpenSim.Region.Framework.Scenes private int m_objectCapacity = 45000; + // This is the number of frames that will be stored and then averaged for + // the Total, Simulation, Physics, and Network Frame Time; It is set to + // 10 by default but can be changed by the OpenSim.ini configuration file + // NumberOfFrames parameter + private int m_numberFramesStored = 10; + + // The arrays that will hold the time it took to run the past N frames, + // where N is the num_frames_to_average given by the configuration file + private double[] m_totalFrameTimeMilliseconds; + private double[] m_simulationFrameTimeMilliseconds; + private double[] m_physicsFrameTimeMilliseconds; + private double[] m_networkFrameTimeMilliseconds; + + // The location of the next time in milliseconds that will be + // (over)written when the next frame completes + private int m_nextLocation = 0; + + // The correct number of frames that have completed since the last stats + // update for physics + private int m_numberPhysicsFrames; + + // The current number of users attempting to login to the region + private int m_usersLoggingIn; + + // The last reported value of threads from the SmartThreadPool inside of + // XEngine + private int m_inUseThreads; + private Scene m_scene; private RegionInfo ReportingRegion; @@ -223,6 +261,15 @@ namespace OpenSim.Region.Framework.Scenes public SimStatsReporter(Scene scene) { + // Initialize the different frame time arrays to the correct sizes + m_totalFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_simulationFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_networkFrameTimeMilliseconds = new double[m_numberFramesStored]; + + // Initialize the current number of users logging into the region + m_usersLoggingIn = 0; + m_scene = scene; m_reportedFpsCorrectionFactor = scene.MinFrameSeconds * m_nominalReportedFps; m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); @@ -256,6 +303,14 @@ namespace OpenSim.Region.Framework.Scenes StatsManager.RegisterStat(SlowFramesStat); } + + public SimStatsReporter(Scene scene, int numberOfFrames) : this (scene) + { + // Store the number of frames from the OpenSim.ini configuration file + m_numberFramesStored = numberOfFrames; + } + + public void Close() { m_report.Elapsed -= TriggerStatsHeartbeat; @@ -289,10 +344,21 @@ namespace OpenSim.Region.Framework.Scenes private void statsHeartBeat(object sender, EventArgs e) { + double totalSumFrameTime; + double simulationSumFrameTime; + double physicsSumFrameTime; + double networkSumFrameTime; + float timeDilation; + int currentFrame; + if (!m_scene.Active) return; - SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[22]; + // Create arrays to hold the statistics for this current scene, + // these will be passed to the SimExtraStatsCollector, they are also + // sent to the SimStats class + SimStatsPacket.StatBlock[] sb = new + SimStatsPacket.StatBlock[m_statisticArraySize]; SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); // Know what's not thread safe in Mono... modifying timers. @@ -314,14 +380,21 @@ namespace OpenSim.Region.Framework.Scenes #region various statistic googly moogly + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window, this will be done as a + // new section given the title of our current project // We're going to lie about the FPS because we've been lying since 2008. The actual FPS is currently // locked at a maximum of 11. Maybe at some point this can change so that we're not lying. - int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); + //int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); + int reportedFPS = m_fps; // save the reported value so there is something available for llGetRegionFPS lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; - float physfps = ((m_pfps / 1000)); + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window + //float physfps = ((m_pfps / 1000)); + float physfps = m_numberPhysicsFrames; //if (physfps > 600) //physfps = physfps - (physfps - 600); @@ -334,6 +407,8 @@ namespace OpenSim.Region.Framework.Scenes m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); m_childAgents = m_scene.SceneGraph.GetChildAgentCount(); m_numPrim = m_scene.SceneGraph.GetTotalObjectsCount(); + m_numGeoPrim = m_scene.SceneGraph.GetTotalPrimObjectsCount(); + m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount(); m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount(); m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount(); @@ -359,13 +434,48 @@ namespace OpenSim.Region.Framework.Scenes if (framesUpdated == 0) framesUpdated = 1; - for (int i = 0; i < 22; i++) + for (int i = 0; i < m_statisticArraySize; i++) { sb[i] = new SimStatsPacket.StatBlock(); } - + + // Resetting the sums of the frame times to prevent any errors + // in calculating the moving average for frame time + totalSumFrameTime = 0; + simulationSumFrameTime = 0; + physicsSumFrameTime = 0; + networkSumFrameTime = 0; + + // Loop through all the frames that were stored for the current + // heartbeat to process the moving average of frame times + for (int i = 0; i < m_numberFramesStored; i++) + { + // Sum up each frame time in order to calculate the moving + // average of frame time + totalSumFrameTime += m_totalFrameTimeMilliseconds[i]; + simulationSumFrameTime += + m_simulationFrameTimeMilliseconds[i]; + physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i]; + networkSumFrameTime += m_networkFrameTimeMilliseconds[i]; + } + + // Get the index that represents the current frame based on the next one known; go back + // to the last index if next one is stated to restart at 0 + if (m_nextLocation == 0) + currentFrame = m_numberFramesStored - 1; + else + currentFrame = m_nextLocation - 1; + + // Calculate the time dilation; which is currently based on the ratio between the sum of the + // physics and simulation rate, and the set minimum time to run the scene's update; minFrameTime + // is given in seconds so multiply by 1000 to convert it to milliseconds + timeDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] + + m_physicsFrameTimeMilliseconds[currentFrame]) / (m_scene.MinFrameTime * 1000); + + // ORIGINAL code commented out until we have time to add our own sb[0].StatID = (uint) Stats.TimeDilation; - sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); + //sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); + sb[0].StatValue = timeDilation; sb[1].StatID = (uint) Stats.SimFPS; sb[1].StatValue = reportedFPS / m_statsUpdateFactor; @@ -388,20 +498,27 @@ namespace OpenSim.Region.Framework.Scenes sb[7].StatID = (uint) Stats.ActivePrim; sb[7].StatValue = m_activePrim; + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window sb[8].StatID = (uint)Stats.FrameMS; - sb[8].StatValue = m_frameMS / framesUpdated; + //sb[8].StatValue = m_frameMS / framesUpdated; + sb[8].StatValue = (float) totalSumFrameTime / m_numberFramesStored; sb[9].StatID = (uint)Stats.NetMS; - sb[9].StatValue = m_netMS / framesUpdated; + //sb[9].StatValue = m_netMS / framesUpdated; + sb[9].StatValue = (float) networkSumFrameTime / m_numberFramesStored; sb[10].StatID = (uint)Stats.PhysicsMS; - sb[10].StatValue = m_physicsMS / framesUpdated; + //sb[10].StatValue = m_physicsMS / framesUpdated; + sb[10].StatValue = (float) physicsSumFrameTime / m_numberFramesStored; sb[11].StatID = (uint)Stats.ImageMS ; sb[11].StatValue = m_imageMS / framesUpdated; sb[12].StatID = (uint)Stats.OtherMS; - sb[12].StatValue = m_otherMS / framesUpdated; + //sb[12].StatValue = m_otherMS / framesUpdated; + sb[12].StatValue = (float) simulationSumFrameTime / + m_numberFramesStored; sb[13].StatID = (uint)Stats.InPacketsPerSecond; sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); @@ -430,7 +547,25 @@ namespace OpenSim.Region.Framework.Scenes sb[21].StatID = (uint)Stats.SimSpareMs; sb[21].StatValue = m_spareMS / framesUpdated; - for (int i = 0; i < 22; i++) + // Added to track the number of users currently attempting to + // login to the region + sb[22].StatID = (uint)Stats.UsersLoggingIn; + sb[22].StatValue = m_usersLoggingIn; + + // Total number of geometric primitives in the scene + sb[23].StatID = (uint)Stats.TotalGeoPrim; + sb[23].StatValue = m_numGeoPrim; + + // Total number of mesh objects in the scene + sb[24].StatID = (uint)Stats.TotalMesh; + sb[24].StatValue = m_numMesh; + + // Added to track the current number of threads that XEngine is + // using + sb[25].StatID = (uint)Stats.ThreadCount; + sb[25].StatValue = m_inUseThreads; + + for (int i = 0; i < m_statisticArraySize; i++) { lastReportedSimStats[i] = sb[i].StatValue; } @@ -475,6 +610,10 @@ namespace OpenSim.Region.Framework.Scenes private void ResetValues() { + // Reset the number of frames that the physics library has + // processed since the last stats report + m_numberPhysicsFrames = 0; + m_timeDilation = 0; m_fps = 0; m_pfps = 0; @@ -605,6 +744,32 @@ namespace OpenSim.Region.Framework.Scenes m_otherMS += ms; } + public void addPhysicsFrame(int frames) + { + // Add the number of physics frames to the correct total physics + // frames + m_numberPhysicsFrames += frames; + } + + public void addFrameTimeMilliseconds(double total, double simulation, + double physics, double network) + { + // Save the frame times from the current frame into the appropriate + // arrays + m_totalFrameTimeMilliseconds[m_nextLocation] = total; + m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation; + m_physicsFrameTimeMilliseconds[m_nextLocation] = physics; + m_networkFrameTimeMilliseconds[m_nextLocation] = network; + + // Update to the next location in the list + m_nextLocation++; + + // Since the list will begin to overwrite the oldest frame values + // first, the next location needs to loop back to the beginning of the + // list whenever it reaches the end + m_nextLocation = m_nextLocation % m_numberFramesStored; + } + public void AddPendingDownloads(int count) { m_pendingDownloads += count; @@ -627,6 +792,31 @@ namespace OpenSim.Region.Framework.Scenes AddunAckedBytes(unAckedBytes); } + public void UpdateUsersLoggingIn(bool isLoggingIn) + { + // Determine whether the user has started logging in or has completed + // logging into the region + if (isLoggingIn) + { + // The user is starting to login to the region so increment the + // number of users attempting to login to the region + m_usersLoggingIn++; + } + else + { + // The user has finished logging into the region so decrement the + // number of users logging into the region + m_usersLoggingIn--; + } + } + + public void SetThreadCount(int inUseThreads) + { + // Save the new number of threads to our member variable to send to + // the extra stats collector + m_inUseThreads = inUseThreads; + } + #endregion public Dictionary GetExtraSimStats() diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs old mode 100644 new mode 100755 index 54620d1c24..4e383f805f --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1872,6 +1872,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) instance.ApiResetScript(); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void ResetScript(UUID itemID) @@ -1879,6 +1885,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) instance.ResetScript(m_WaitForEventCompletionOnScriptStop); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void StartScript(UUID itemID) @@ -1888,6 +1900,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.Start(); else m_runFlags.AddOrUpdate(itemID, true, 240); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void StopScript(UUID itemID) @@ -1903,6 +1921,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine // m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name); m_runFlags.AddOrUpdate(itemID, false, 240); } + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public DetectParams GetDetectParams(UUID itemID, int idx) @@ -2393,6 +2417,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.Suspend(); // else // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public void ResumeScript(UUID itemID) @@ -2404,6 +2434,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.Resume(); // else // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); + + // Send the new number of threads that are in use by the thread + // pool, I believe that by adding them to the locations where the + // script is changing states that I will catch all changes to the + // thread pool + m_Scene.setThreadCount(m_ThreadPool.InUseThreads); } public bool HasScript(UUID itemID, out bool running) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini old mode 100644 new mode 100755 index af37ccc0f0..3422996f7f --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -296,7 +296,7 @@ ; Simulator Stats URI ; Enable JSON simulator data by setting a URI name (case sensitive) ; Returns regular sim stats (SimFPS, ...) - ; Stats_URI = "jsonSimStats" + Stats_URI = "jsonSimStats" ; Simulator StatsManager URI ; Enable fetch of StatsManager registered stats. Fetch is query which can optionally