diff options
author | Justin Clark-Casey (justincc) | 2012-10-04 00:32:42 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-10-04 00:32:42 +0100 |
commit | e717398f6c72bdb30e59468462f3a5f589c1bb35 (patch) | |
tree | 0b917b2ee0670c72d8e8897c18e7f9bcd87dd92d | |
parent | Soliciting for comments on smoothness of physics objects for this build. (diff) | |
download | opensim-SC-e717398f6c72bdb30e59468462f3a5f589c1bb35.zip opensim-SC-e717398f6c72bdb30e59468462f3a5f589c1bb35.tar.gz opensim-SC-e717398f6c72bdb30e59468462f3a5f589c1bb35.tar.bz2 opensim-SC-e717398f6c72bdb30e59468462f3a5f589c1bb35.tar.xz |
Add experimental "slow frames" stat, available in "show stats" and via the monitoring module.
This increments a SlowFrames counter if a frame takes over 120% of maximum time.
This commit also introduces a generic OpenSim.Framework.Monitoring.Stat which is available to any code that wants to register a statistic.
This is more granualar than asking objects to create their own reports.
At some point this will supersede earlier IMonitor and IAlert facilities in MonitoringModule which are only available to scene code.
-rw-r--r-- | OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | 13 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/StatsManager.cs | 114 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 33 |
3 files changed, 158 insertions, 2 deletions
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index cdd7cc7..8ac9090 100644 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | |||
@@ -355,10 +355,19 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
355 | sb.Append(Environment.NewLine); | 355 | sb.Append(Environment.NewLine); |
356 | sb.Append( | 356 | sb.Append( |
357 | string.Format( | 357 | string.Format( |
358 | "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", | 358 | "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}\n\n", |
359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, | 359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, |
360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); | 360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); |
361 | sb.Append(Environment.NewLine); | 361 | |
362 | foreach (KeyValuePair<string, Stat> kvp in StatsManager.RegisteredStats) | ||
363 | { | ||
364 | Stat stat = kvp.Value; | ||
365 | |||
366 | if (stat.Category == "scene" && stat.Verbosity == StatVerbosity.Info) | ||
367 | { | ||
368 | sb.AppendFormat("Slow frames ({0}): {1}\n", stat.Container, stat.Value); | ||
369 | } | ||
370 | } | ||
362 | 371 | ||
363 | /* | 372 | /* |
364 | sb.Append(Environment.NewLine); | 373 | sb.Append(Environment.NewLine); |
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index d78fa6a..02df0ac 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs | |||
@@ -25,6 +25,9 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | |||
28 | namespace OpenSim.Framework.Monitoring | 31 | namespace OpenSim.Framework.Monitoring |
29 | { | 32 | { |
30 | /// <summary> | 33 | /// <summary> |
@@ -32,6 +35,14 @@ namespace OpenSim.Framework.Monitoring | |||
32 | /// </summary> | 35 | /// </summary> |
33 | public class StatsManager | 36 | public class StatsManager |
34 | { | 37 | { |
38 | /// <summary> | ||
39 | /// Registered stats. | ||
40 | /// </summary> | ||
41 | /// <remarks> | ||
42 | /// Do not add or remove from this dictionary. | ||
43 | /// </remarks> | ||
44 | public static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); | ||
45 | |||
35 | private static AssetStatsCollector assetStats; | 46 | private static AssetStatsCollector assetStats; |
36 | private static UserStatsCollector userStats; | 47 | private static UserStatsCollector userStats; |
37 | private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); | 48 | private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); |
@@ -61,5 +72,108 @@ namespace OpenSim.Framework.Monitoring | |||
61 | 72 | ||
62 | return userStats; | 73 | return userStats; |
63 | } | 74 | } |
75 | |||
76 | public static bool RegisterStat(Stat stat) | ||
77 | { | ||
78 | lock (RegisteredStats) | ||
79 | { | ||
80 | if (RegisteredStats.ContainsKey(stat.UniqueName)) | ||
81 | { | ||
82 | // XXX: For now just return false. This is to avoid problems in regression tests where all tests | ||
83 | // in a class are run in the same instance of the VM. | ||
84 | return false; | ||
85 | |||
86 | // throw new Exception( | ||
87 | // "StatsManager already contains stat with ShortName {0} in Category {1}", stat.ShortName, stat.Category); | ||
88 | } | ||
89 | |||
90 | // We take a replace-on-write approach here so that we don't need to generate a new Dictionary | ||
91 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | ||
92 | newRegisteredStats[stat.UniqueName] = stat; | ||
93 | RegisteredStats = newRegisteredStats; | ||
94 | } | ||
95 | |||
96 | return true; | ||
97 | } | ||
98 | |||
99 | public static bool DeregisterStat(Stat stat) | ||
100 | { | ||
101 | lock (RegisteredStats) | ||
102 | { | ||
103 | if (!RegisteredStats.ContainsKey(stat.UniqueName)) | ||
104 | return false; | ||
105 | |||
106 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | ||
107 | newRegisteredStats.Remove(stat.UniqueName); | ||
108 | RegisteredStats = newRegisteredStats; | ||
109 | |||
110 | return true; | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /// <summary> | ||
116 | /// Verbosity of stat. | ||
117 | /// </summary> | ||
118 | /// <remarks> | ||
119 | /// Info will always be displayed. | ||
120 | /// </remarks> | ||
121 | public enum StatVerbosity | ||
122 | { | ||
123 | Debug, | ||
124 | Info | ||
125 | } | ||
126 | |||
127 | /// <summary> | ||
128 | /// Holds individual static details | ||
129 | /// </summary> | ||
130 | public class Stat | ||
131 | { | ||
132 | /// <summary> | ||
133 | /// Unique stat name used for indexing. Each ShortName in a Category must be unique. | ||
134 | /// </summary> | ||
135 | public string UniqueName { get; private set; } | ||
136 | |||
137 | /// <summary> | ||
138 | /// Category of this stat (e.g. cache, scene, etc). | ||
139 | /// </summary> | ||
140 | public string Category { get; private set; } | ||
141 | |||
142 | /// <summary> | ||
143 | /// Containing name for this stat. | ||
144 | /// FIXME: In the case of a scene, this is currently the scene name (though this leaves | ||
145 | /// us with a to-be-resolved problem of non-unique region names). | ||
146 | /// </summary> | ||
147 | /// <value> | ||
148 | /// The container. | ||
149 | /// </value> | ||
150 | public string Container { get; private set; } | ||
151 | |||
152 | public StatVerbosity Verbosity { get; private set; } | ||
153 | public string ShortName { get; private set; } | ||
154 | public string Name { get; private set; } | ||
155 | public string Description { get; private set; } | ||
156 | public string UnitName { get; private set; } | ||
157 | |||
158 | public double Value { get; set; } | ||
159 | |||
160 | public Stat( | ||
161 | string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) | ||
162 | { | ||
163 | ShortName = shortName; | ||
164 | Name = name; | ||
165 | UnitName = unitName; | ||
166 | Category = category; | ||
167 | Container = container; | ||
168 | Verbosity = verbosity; | ||
169 | Description = description; | ||
170 | |||
171 | UniqueName = GenUniqueName(Container, Category, ShortName); | ||
172 | } | ||
173 | |||
174 | public static string GenUniqueName(string container, string category, string shortName) | ||
175 | { | ||
176 | return string.Format("{0}+{1}+{2}", container, category, shortName); | ||
177 | } | ||
64 | } | 178 | } |
65 | } \ No newline at end of file | 179 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 96317c3..b7b5ea2 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -47,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; | 49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; |
50 | public const string SlowFramesStatName = "SlowFrames"; | ||
50 | 51 | ||
51 | public delegate void SendStatResult(SimStats stats); | 52 | public delegate void SendStatResult(SimStats stats); |
52 | 53 | ||
@@ -129,6 +130,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
129 | } | 130 | } |
130 | 131 | ||
131 | /// <summary> | 132 | /// <summary> |
133 | /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME | ||
134 | /// </summary> | ||
135 | public Stat SlowFramesStat { get; private set; } | ||
136 | |||
137 | /// <summary> | ||
138 | /// The threshold at which we log a slow frame. | ||
139 | /// </summary> | ||
140 | public int SlowFramesStatReportThreshold { get; private set; } | ||
141 | |||
142 | /// <summary> | ||
132 | /// Extra sim statistics that are used by monitors but not sent to the client. | 143 | /// Extra sim statistics that are used by monitors but not sent to the client. |
133 | /// </summary> | 144 | /// </summary> |
134 | /// <value> | 145 | /// <value> |
@@ -225,6 +236,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
225 | 236 | ||
226 | if (StatsManager.SimExtraStats != null) | 237 | if (StatsManager.SimExtraStats != null) |
227 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; | 238 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; |
239 | |||
240 | /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
241 | /// longer than ideal (which in itself is a concern). | ||
242 | SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); | ||
243 | |||
244 | SlowFramesStat | ||
245 | = new Stat( | ||
246 | "SlowFrames", | ||
247 | "Slow Frames", | ||
248 | "frames", | ||
249 | "scene", | ||
250 | m_scene.Name, | ||
251 | StatVerbosity.Info, | ||
252 | "Number of frames where frame time has been significantly longer than the desired frame time."); | ||
253 | |||
254 | StatsManager.RegisterStat(SlowFramesStat); | ||
228 | } | 255 | } |
229 | 256 | ||
230 | public void Close() | 257 | public void Close() |
@@ -418,6 +445,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
418 | lock (m_lastReportedExtraSimStats) | 445 | lock (m_lastReportedExtraSimStats) |
419 | { | 446 | { |
420 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; | 447 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; |
448 | m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; | ||
421 | 449 | ||
422 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); | 450 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); |
423 | 451 | ||
@@ -535,6 +563,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
535 | public void addFrameMS(int ms) | 563 | public void addFrameMS(int ms) |
536 | { | 564 | { |
537 | m_frameMS += ms; | 565 | m_frameMS += ms; |
566 | |||
567 | // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
568 | // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). | ||
569 | if (ms > SlowFramesStatReportThreshold) | ||
570 | SlowFramesStat.Value++; | ||
538 | } | 571 | } |
539 | 572 | ||
540 | public void AddSpareMS(int ms) | 573 | public void AddSpareMS(int ms) |