diff options
author | Justin Clark-Casey (justincc) | 2012-05-31 01:52:26 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-05-31 01:52:26 +0100 |
commit | 0b02a4d42e989609a4e1ba39d2aee9a7f9655613 (patch) | |
tree | 353e05997fb8478cb6b3691edc943604e5dd78ff /OpenSim/Region | |
parent | Add console command "teleport user" to allow teleport from the region console (diff) | |
download | opensim-SC-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.zip opensim-SC-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.gz opensim-SC-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.bz2 opensim-SC-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.xz |
Add an optional mechanism for physics modules to collect and return arbitrary stats.
If active, the physics module can return arbitrary stat counters that can be seen via the MonitoringModule
(http://opensimulator.org/wiki/Monitoring_Module)
This is only active in OdeScene if collect_stats = true in [ODEPhysicsSettings].
This patch allows OdeScene to collect elapsed time information for calls to the ODE native collision methods to assess what proportion of time this takes compared to total physics processing.
This data is returned as ODENativeCollisionFrameMS in the monitoring module, updated every 3 seconds.
The performance effect of collecting stats is probably extremely minor, dwarfed by the rest of the physics code.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/Application/OpenSim.cs | 3 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | 108 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 48 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Manager/PhysicsScene.cs | 14 | ||||
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 139 |
5 files changed, 252 insertions, 60 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 6796f2b..c0913c5 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Diagnostics; | ||
31 | using System.IO; | 32 | using System.IO; |
32 | using System.Reflection; | 33 | using System.Reflection; |
33 | using System.Text; | 34 | using System.Text; |
@@ -138,7 +139,7 @@ namespace OpenSim | |||
138 | m_log.Info("===================================================================="); | 139 | m_log.Info("===================================================================="); |
139 | m_log.Info("========================= STARTING OPENSIM ========================="); | 140 | m_log.Info("========================= STARTING OPENSIM ========================="); |
140 | m_log.Info("===================================================================="); | 141 | m_log.Info("===================================================================="); |
141 | 142 | ||
142 | //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString()); | 143 | //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString()); |
143 | // http://msdn.microsoft.com/en-us/library/bb384202.aspx | 144 | // http://msdn.microsoft.com/en-us/library/bb384202.aspx |
144 | //GCSettings.LatencyMode = GCLatencyMode.Batch; | 145 | //GCSettings.LatencyMode = GCLatencyMode.Batch; |
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index 7f8271d..4a8c369 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | |||
@@ -49,7 +49,16 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
49 | public bool Enabled { get; private set; } | 49 | public bool Enabled { get; private set; } |
50 | 50 | ||
51 | private Scene m_scene; | 51 | private Scene m_scene; |
52 | private readonly List<IMonitor> m_monitors = new List<IMonitor>(); | 52 | |
53 | /// <summary> | ||
54 | /// These are monitors where we know the static details in advance. | ||
55 | /// </summary> | ||
56 | /// <remarks> | ||
57 | /// Dynamic monitors also exist (we don't know any of the details of what stats we get back here) | ||
58 | /// but these are currently hardcoded. | ||
59 | /// </remarks> | ||
60 | private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>(); | ||
61 | |||
53 | private readonly List<IAlert> m_alerts = new List<IAlert>(); | 62 | private readonly List<IAlert> m_alerts = new List<IAlert>(); |
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 63 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
55 | 64 | ||
@@ -84,9 +93,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
84 | 93 | ||
85 | public void DebugMonitors(string module, string[] args) | 94 | public void DebugMonitors(string module, string[] args) |
86 | { | 95 | { |
87 | foreach (IMonitor monitor in m_monitors) | 96 | foreach (IMonitor monitor in m_staticMonitors) |
88 | { | 97 | { |
89 | m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue()); | 98 | m_log.InfoFormat( |
99 | "[MONITOR MODULE]: {0} reports {1} = {2}", | ||
100 | m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); | ||
101 | } | ||
102 | |||
103 | foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) | ||
104 | { | ||
105 | m_log.InfoFormat( | ||
106 | "[MONITOR MODULE]: {0} reports {1} = {2}", | ||
107 | m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); | ||
90 | } | 108 | } |
91 | } | 109 | } |
92 | 110 | ||
@@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
106 | { | 124 | { |
107 | string monID = (string) request["monitor"]; | 125 | string monID = (string) request["monitor"]; |
108 | 126 | ||
109 | foreach (IMonitor monitor in m_monitors) | 127 | foreach (IMonitor monitor in m_staticMonitors) |
110 | { | 128 | { |
111 | string elemName = monitor.ToString(); | 129 | string elemName = monitor.ToString(); |
112 | if (elemName.StartsWith(monitor.GetType().Namespace)) | 130 | if (elemName.StartsWith(monitor.GetType().Namespace)) |
113 | elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1); | 131 | elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1); |
132 | |||
114 | if (elemName == monID || monitor.ToString() == monID) | 133 | if (elemName == monID || monitor.ToString() == monID) |
115 | { | 134 | { |
116 | Hashtable ereply3 = new Hashtable(); | 135 | Hashtable ereply3 = new Hashtable(); |
@@ -123,6 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
123 | } | 142 | } |
124 | } | 143 | } |
125 | 144 | ||
145 | // FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code | ||
146 | // is even doing. Why are we inspecting the type of the monitor??? | ||
147 | |||
126 | // No monitor with that name | 148 | // No monitor with that name |
127 | Hashtable ereply2 = new Hashtable(); | 149 | Hashtable ereply2 = new Hashtable(); |
128 | 150 | ||
@@ -134,12 +156,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
134 | } | 156 | } |
135 | 157 | ||
136 | string xml = "<data>"; | 158 | string xml = "<data>"; |
137 | foreach (IMonitor monitor in m_monitors) | 159 | foreach (IMonitor monitor in m_staticMonitors) |
138 | { | 160 | { |
139 | string elemName = monitor.GetName(); | 161 | string elemName = monitor.GetName(); |
140 | xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">"; | 162 | xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">"; |
141 | // m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue()); | 163 | // m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue()); |
142 | } | 164 | } |
165 | |||
166 | foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) | ||
167 | { | ||
168 | xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">"; | ||
169 | } | ||
170 | |||
143 | xml += "</data>"; | 171 | xml += "</data>"; |
144 | 172 | ||
145 | Hashtable ereply = new Hashtable(); | 173 | Hashtable ereply = new Hashtable(); |
@@ -156,20 +184,20 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
156 | if (!Enabled) | 184 | if (!Enabled) |
157 | return; | 185 | return; |
158 | 186 | ||
159 | m_monitors.Add(new AgentCountMonitor(m_scene)); | 187 | m_staticMonitors.Add(new AgentCountMonitor(m_scene)); |
160 | m_monitors.Add(new ChildAgentCountMonitor(m_scene)); | 188 | m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene)); |
161 | m_monitors.Add(new GCMemoryMonitor()); | 189 | m_staticMonitors.Add(new GCMemoryMonitor()); |
162 | m_monitors.Add(new ObjectCountMonitor(m_scene)); | 190 | m_staticMonitors.Add(new ObjectCountMonitor(m_scene)); |
163 | m_monitors.Add(new PhysicsFrameMonitor(m_scene)); | 191 | m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene)); |
164 | m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene)); | 192 | m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene)); |
165 | m_monitors.Add(new PWSMemoryMonitor()); | 193 | m_staticMonitors.Add(new PWSMemoryMonitor()); |
166 | m_monitors.Add(new ThreadCountMonitor()); | 194 | m_staticMonitors.Add(new ThreadCountMonitor()); |
167 | m_monitors.Add(new TotalFrameMonitor(m_scene)); | 195 | m_staticMonitors.Add(new TotalFrameMonitor(m_scene)); |
168 | m_monitors.Add(new EventFrameMonitor(m_scene)); | 196 | m_staticMonitors.Add(new EventFrameMonitor(m_scene)); |
169 | m_monitors.Add(new LandFrameMonitor(m_scene)); | 197 | m_staticMonitors.Add(new LandFrameMonitor(m_scene)); |
170 | m_monitors.Add(new LastFrameTimeMonitor(m_scene)); | 198 | m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene)); |
171 | 199 | ||
172 | m_monitors.Add( | 200 | m_staticMonitors.Add( |
173 | new GenericMonitor( | 201 | new GenericMonitor( |
174 | m_scene, | 202 | m_scene, |
175 | "TimeDilationMonitor", | 203 | "TimeDilationMonitor", |
@@ -177,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
177 | m => m.Scene.StatsReporter.LastReportedSimStats[0], | 205 | m => m.Scene.StatsReporter.LastReportedSimStats[0], |
178 | m => m.GetValue().ToString())); | 206 | m => m.GetValue().ToString())); |
179 | 207 | ||
180 | m_monitors.Add( | 208 | m_staticMonitors.Add( |
181 | new GenericMonitor( | 209 | new GenericMonitor( |
182 | m_scene, | 210 | m_scene, |
183 | "SimFPSMonitor", | 211 | "SimFPSMonitor", |
@@ -185,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
185 | m => m.Scene.StatsReporter.LastReportedSimStats[1], | 213 | m => m.Scene.StatsReporter.LastReportedSimStats[1], |
186 | m => string.Format("{0}", m.GetValue()))); | 214 | m => string.Format("{0}", m.GetValue()))); |
187 | 215 | ||
188 | m_monitors.Add( | 216 | m_staticMonitors.Add( |
189 | new GenericMonitor( | 217 | new GenericMonitor( |
190 | m_scene, | 218 | m_scene, |
191 | "PhysicsFPSMonitor", | 219 | "PhysicsFPSMonitor", |
@@ -193,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
193 | m => m.Scene.StatsReporter.LastReportedSimStats[2], | 221 | m => m.Scene.StatsReporter.LastReportedSimStats[2], |
194 | m => string.Format("{0}", m.GetValue()))); | 222 | m => string.Format("{0}", m.GetValue()))); |
195 | 223 | ||
196 | m_monitors.Add( | 224 | m_staticMonitors.Add( |
197 | new GenericMonitor( | 225 | new GenericMonitor( |
198 | m_scene, | 226 | m_scene, |
199 | "AgentUpdatesPerSecondMonitor", | 227 | "AgentUpdatesPerSecondMonitor", |
@@ -201,15 +229,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
201 | m => m.Scene.StatsReporter.LastReportedSimStats[3], | 229 | m => m.Scene.StatsReporter.LastReportedSimStats[3], |
202 | m => string.Format("{0} per second", m.GetValue()))); | 230 | m => string.Format("{0} per second", m.GetValue()))); |
203 | 231 | ||
204 | m_monitors.Add( | 232 | m_staticMonitors.Add( |
205 | new GenericMonitor( | ||
206 | m_scene, | ||
207 | "ObjectUpdatesPerSecondMonitor", | ||
208 | "Object Updates", | ||
209 | m => m.Scene.StatsReporter.LastReportedObjectUpdates, | ||
210 | m => string.Format("{0} per second", m.GetValue()))); | ||
211 | |||
212 | m_monitors.Add( | ||
213 | new GenericMonitor( | 233 | new GenericMonitor( |
214 | m_scene, | 234 | m_scene, |
215 | "ActiveObjectCountMonitor", | 235 | "ActiveObjectCountMonitor", |
@@ -217,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
217 | m => m.Scene.StatsReporter.LastReportedSimStats[7], | 237 | m => m.Scene.StatsReporter.LastReportedSimStats[7], |
218 | m => string.Format("{0}", m.GetValue()))); | 238 | m => string.Format("{0}", m.GetValue()))); |
219 | 239 | ||
220 | m_monitors.Add( | 240 | m_staticMonitors.Add( |
221 | new GenericMonitor( | 241 | new GenericMonitor( |
222 | m_scene, | 242 | m_scene, |
223 | "ActiveScriptsMonitor", | 243 | "ActiveScriptsMonitor", |
@@ -225,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
225 | m => m.Scene.StatsReporter.LastReportedSimStats[19], | 245 | m => m.Scene.StatsReporter.LastReportedSimStats[19], |
226 | m => string.Format("{0}", m.GetValue()))); | 246 | m => string.Format("{0}", m.GetValue()))); |
227 | 247 | ||
228 | m_monitors.Add( | 248 | m_staticMonitors.Add( |
229 | new GenericMonitor( | 249 | new GenericMonitor( |
230 | m_scene, | 250 | m_scene, |
231 | "ScriptEventsPerSecondMonitor", | 251 | "ScriptEventsPerSecondMonitor", |
@@ -233,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
233 | m => m.Scene.StatsReporter.LastReportedSimStats[20], | 253 | m => m.Scene.StatsReporter.LastReportedSimStats[20], |
234 | m => string.Format("{0} per second", m.GetValue()))); | 254 | m => string.Format("{0} per second", m.GetValue()))); |
235 | 255 | ||
236 | m_monitors.Add( | 256 | m_staticMonitors.Add( |
237 | new GenericMonitor( | 257 | new GenericMonitor( |
238 | m_scene, | 258 | m_scene, |
239 | "InPacketsPerSecondMonitor", | 259 | "InPacketsPerSecondMonitor", |
@@ -241,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
241 | m => m.Scene.StatsReporter.LastReportedSimStats[13], | 261 | m => m.Scene.StatsReporter.LastReportedSimStats[13], |
242 | m => string.Format("{0} per second", m.GetValue()))); | 262 | m => string.Format("{0} per second", m.GetValue()))); |
243 | 263 | ||
244 | m_monitors.Add( | 264 | m_staticMonitors.Add( |
245 | new GenericMonitor( | 265 | new GenericMonitor( |
246 | m_scene, | 266 | m_scene, |
247 | "OutPacketsPerSecondMonitor", | 267 | "OutPacketsPerSecondMonitor", |
@@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
249 | m => m.Scene.StatsReporter.LastReportedSimStats[14], | 269 | m => m.Scene.StatsReporter.LastReportedSimStats[14], |
250 | m => string.Format("{0} per second", m.GetValue()))); | 270 | m => string.Format("{0} per second", m.GetValue()))); |
251 | 271 | ||
252 | m_monitors.Add( | 272 | m_staticMonitors.Add( |
253 | new GenericMonitor( | 273 | new GenericMonitor( |
254 | m_scene, | 274 | m_scene, |
255 | "UnackedBytesMonitor", | 275 | "UnackedBytesMonitor", |
@@ -257,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
257 | m => m.Scene.StatsReporter.LastReportedSimStats[15], | 277 | m => m.Scene.StatsReporter.LastReportedSimStats[15], |
258 | m => string.Format("{0}", m.GetValue()))); | 278 | m => string.Format("{0}", m.GetValue()))); |
259 | 279 | ||
260 | m_monitors.Add( | 280 | m_staticMonitors.Add( |
261 | new GenericMonitor( | 281 | new GenericMonitor( |
262 | m_scene, | 282 | m_scene, |
263 | "PendingDownloadsMonitor", | 283 | "PendingDownloadsMonitor", |
@@ -265,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
265 | m => m.Scene.StatsReporter.LastReportedSimStats[17], | 285 | m => m.Scene.StatsReporter.LastReportedSimStats[17], |
266 | m => string.Format("{0}", m.GetValue()))); | 286 | m => string.Format("{0}", m.GetValue()))); |
267 | 287 | ||
268 | m_monitors.Add( | 288 | m_staticMonitors.Add( |
269 | new GenericMonitor( | 289 | new GenericMonitor( |
270 | m_scene, | 290 | m_scene, |
271 | "PendingUploadsMonitor", | 291 | "PendingUploadsMonitor", |
@@ -273,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
273 | m => m.Scene.StatsReporter.LastReportedSimStats[18], | 293 | m => m.Scene.StatsReporter.LastReportedSimStats[18], |
274 | m => string.Format("{0}", m.GetValue()))); | 294 | m => string.Format("{0}", m.GetValue()))); |
275 | 295 | ||
276 | m_monitors.Add( | 296 | m_staticMonitors.Add( |
277 | new GenericMonitor( | 297 | new GenericMonitor( |
278 | m_scene, | 298 | m_scene, |
279 | "TotalFrameTimeMonitor", | 299 | "TotalFrameTimeMonitor", |
@@ -281,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
281 | m => m.Scene.StatsReporter.LastReportedSimStats[8], | 301 | m => m.Scene.StatsReporter.LastReportedSimStats[8], |
282 | m => string.Format("{0} ms", m.GetValue()))); | 302 | m => string.Format("{0} ms", m.GetValue()))); |
283 | 303 | ||
284 | m_monitors.Add( | 304 | m_staticMonitors.Add( |
285 | new GenericMonitor( | 305 | new GenericMonitor( |
286 | m_scene, | 306 | m_scene, |
287 | "NetFrameTimeMonitor", | 307 | "NetFrameTimeMonitor", |
@@ -289,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
289 | m => m.Scene.StatsReporter.LastReportedSimStats[9], | 309 | m => m.Scene.StatsReporter.LastReportedSimStats[9], |
290 | m => string.Format("{0} ms", m.GetValue()))); | 310 | m => string.Format("{0} ms", m.GetValue()))); |
291 | 311 | ||
292 | m_monitors.Add( | 312 | m_staticMonitors.Add( |
293 | new GenericMonitor( | 313 | new GenericMonitor( |
294 | m_scene, | 314 | m_scene, |
295 | "PhysicsFrameTimeMonitor", | 315 | "PhysicsFrameTimeMonitor", |
@@ -297,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
297 | m => m.Scene.StatsReporter.LastReportedSimStats[10], | 317 | m => m.Scene.StatsReporter.LastReportedSimStats[10], |
298 | m => string.Format("{0} ms", m.GetValue()))); | 318 | m => string.Format("{0} ms", m.GetValue()))); |
299 | 319 | ||
300 | m_monitors.Add( | 320 | m_staticMonitors.Add( |
301 | new GenericMonitor( | 321 | new GenericMonitor( |
302 | m_scene, | 322 | m_scene, |
303 | "SimulationFrameTimeMonitor", | 323 | "SimulationFrameTimeMonitor", |
@@ -305,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
305 | m => m.Scene.StatsReporter.LastReportedSimStats[12], | 325 | m => m.Scene.StatsReporter.LastReportedSimStats[12], |
306 | m => string.Format("{0} ms", m.GetValue()))); | 326 | m => string.Format("{0} ms", m.GetValue()))); |
307 | 327 | ||
308 | m_monitors.Add( | 328 | m_staticMonitors.Add( |
309 | new GenericMonitor( | 329 | new GenericMonitor( |
310 | m_scene, | 330 | m_scene, |
311 | "AgentFrameTimeMonitor", | 331 | "AgentFrameTimeMonitor", |
@@ -313,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
313 | m => m.Scene.StatsReporter.LastReportedSimStats[16], | 333 | m => m.Scene.StatsReporter.LastReportedSimStats[16], |
314 | m => string.Format("{0} ms", m.GetValue()))); | 334 | m => string.Format("{0} ms", m.GetValue()))); |
315 | 335 | ||
316 | m_monitors.Add( | 336 | m_staticMonitors.Add( |
317 | new GenericMonitor( | 337 | new GenericMonitor( |
318 | m_scene, | 338 | m_scene, |
319 | "ImagesFrameTimeMonitor", | 339 | "ImagesFrameTimeMonitor", |
@@ -321,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
321 | m => m.Scene.StatsReporter.LastReportedSimStats[11], | 341 | m => m.Scene.StatsReporter.LastReportedSimStats[11], |
322 | m => string.Format("{0} ms", m.GetValue()))); | 342 | m => string.Format("{0} ms", m.GetValue()))); |
323 | 343 | ||
324 | m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); | 344 | m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); |
325 | 345 | ||
326 | foreach (IAlert alert in m_alerts) | 346 | foreach (IAlert alert in m_alerts) |
327 | { | 347 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 5c56264..08d8d7c 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -26,7 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | //using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Timers; | 30 | using System.Timers; |
31 | using OpenMetaverse.Packets; | 31 | using OpenMetaverse.Packets; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
@@ -35,10 +35,18 @@ using OpenSim.Region.Framework.Interfaces; | |||
35 | 35 | ||
36 | namespace OpenSim.Region.Framework.Scenes | 36 | namespace OpenSim.Region.Framework.Scenes |
37 | { | 37 | { |
38 | /// <summary> | ||
39 | /// Collect statistics from the scene to send to the client and for access by other monitoring tools. | ||
40 | /// </summary> | ||
41 | /// <remarks> | ||
42 | /// FIXME: This should be a monitoring region module | ||
43 | /// </remarks> | ||
38 | public class SimStatsReporter | 44 | public class SimStatsReporter |
39 | { | 45 | { |
40 | // private static readonly log4net.ILog m_log | 46 | private static readonly log4net.ILog m_log |
41 | // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
48 | |||
49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; | ||
42 | 50 | ||
43 | public delegate void SendStatResult(SimStats stats); | 51 | public delegate void SendStatResult(SimStats stats); |
44 | 52 | ||
@@ -100,6 +108,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
100 | get { return lastReportedSimStats; } | 108 | get { return lastReportedSimStats; } |
101 | } | 109 | } |
102 | 110 | ||
111 | /// <summary> | ||
112 | /// Extra sim statistics that are used by monitors but not sent to the client. | ||
113 | /// </summary> | ||
114 | /// <value> | ||
115 | /// The keys are the stat names. | ||
116 | /// </value> | ||
117 | private Dictionary<string, float> m_lastReportedExtraSimStats = new Dictionary<string, float>(); | ||
118 | |||
103 | // Sending a stats update every 3 seconds- | 119 | // Sending a stats update every 3 seconds- |
104 | private int statsUpdatesEveryMS = 3000; | 120 | private int statsUpdatesEveryMS = 3000; |
105 | private float statsUpdateFactor = 0; | 121 | private float statsUpdateFactor = 0; |
@@ -334,7 +350,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
334 | } | 350 | } |
335 | 351 | ||
336 | // Extra statistics that aren't currently sent to clients | 352 | // Extra statistics that aren't currently sent to clients |
337 | LastReportedObjectUpdates = m_objectUpdates / statsUpdateFactor; | 353 | lock (m_lastReportedExtraSimStats) |
354 | { | ||
355 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / statsUpdateFactor; | ||
356 | |||
357 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); | ||
358 | |||
359 | if (physicsStats != null) | ||
360 | { | ||
361 | foreach (KeyValuePair<string, float> tuple in physicsStats) | ||
362 | { | ||
363 | m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / statsUpdateFactor; | ||
364 | } | ||
365 | } | ||
366 | } | ||
338 | 367 | ||
339 | resetvalues(); | 368 | resetvalues(); |
340 | } | 369 | } |
@@ -487,7 +516,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
487 | public void AddPendingDownloads(int count) | 516 | public void AddPendingDownloads(int count) |
488 | { | 517 | { |
489 | m_pendingDownloads += count; | 518 | m_pendingDownloads += count; |
490 | if (m_pendingDownloads < 0) m_pendingDownloads = 0; | 519 | |
520 | if (m_pendingDownloads < 0) | ||
521 | m_pendingDownloads = 0; | ||
522 | |||
491 | //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); | 523 | //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); |
492 | } | 524 | } |
493 | 525 | ||
@@ -509,5 +541,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
509 | } | 541 | } |
510 | 542 | ||
511 | #endregion | 543 | #endregion |
544 | |||
545 | public Dictionary<string, float> GetExtraSimStats() | ||
546 | { | ||
547 | lock (m_lastReportedExtraSimStats) | ||
548 | return new Dictionary<string, float>(m_lastReportedExtraSimStats); | ||
549 | } | ||
512 | } | 550 | } |
513 | } | 551 | } |
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 2a6163c..b32cd30 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs | |||
@@ -192,8 +192,22 @@ namespace OpenSim.Region.Physics.Manager | |||
192 | 192 | ||
193 | public abstract void AddPhysicsActorTaint(PhysicsActor prim); | 193 | public abstract void AddPhysicsActorTaint(PhysicsActor prim); |
194 | 194 | ||
195 | /// <summary> | ||
196 | /// Perform a simulation of the current physics scene over the given timestep. | ||
197 | /// </summary> | ||
198 | /// <param name="timeStep"></param> | ||
199 | /// <returns>The number of frames simulated over that period.</returns> | ||
195 | public abstract float Simulate(float timeStep); | 200 | public abstract float Simulate(float timeStep); |
196 | 201 | ||
202 | /// <summary> | ||
203 | /// Get statistics about this scene. | ||
204 | /// </summary> | ||
205 | /// <remarks>This facility is currently experimental and subject to change.</remarks> | ||
206 | /// <returns> | ||
207 | /// A dictionary where the key is the statistic name. If no statistics are supplied then returns null. | ||
208 | /// </returns> | ||
209 | public virtual Dictionary<string, float> GetStats() { return null; } | ||
210 | |||
197 | public abstract void GetResults(); | 211 | public abstract void GetResults(); |
198 | 212 | ||
199 | public abstract void SetTerrain(float[] heightMap); | 213 | public abstract void SetTerrain(float[] heightMap); |
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 409b27b..fa65945 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -131,6 +131,41 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
131 | /// </remarks> | 131 | /// </remarks> |
132 | internal static Object UniversalColliderSyncObject = new Object(); | 132 | internal static Object UniversalColliderSyncObject = new Object(); |
133 | 133 | ||
134 | /// <summary> | ||
135 | /// Is stats collecting enabled for this ODE scene? | ||
136 | /// </summary> | ||
137 | public bool CollectStats { get; set; } | ||
138 | |||
139 | /// <summary> | ||
140 | /// Statistics for this scene. | ||
141 | /// </summary> | ||
142 | private Dictionary<string, float> m_stats = new Dictionary<string, float>(); | ||
143 | |||
144 | /// <summary> | ||
145 | /// Stat name for recording the number of milliseconds that ODE spends in native collision code. | ||
146 | /// </summary> | ||
147 | public const string ODENativeCollisionFrameMsStatName = "ODENativeCollisionFrameMS"; | ||
148 | |||
149 | /// <summary> | ||
150 | /// Used to hold tick numbers for stat collection purposes. | ||
151 | /// </summary> | ||
152 | private int m_nativeCollisionTickRecorder; | ||
153 | |||
154 | /// <summary> | ||
155 | /// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback. | ||
156 | /// </summary> | ||
157 | private bool m_inCollisionTiming; | ||
158 | |||
159 | /// <summary> | ||
160 | /// Used in calculating physics frame time dilation | ||
161 | /// </summary> | ||
162 | private int tickCountFrameRun; | ||
163 | |||
164 | /// <summary> | ||
165 | /// Used in calculating physics frame time dilation | ||
166 | /// </summary> | ||
167 | private int latertickcount; | ||
168 | |||
134 | private Random fluidRandomizer = new Random(Environment.TickCount); | 169 | private Random fluidRandomizer = new Random(Environment.TickCount); |
135 | 170 | ||
136 | private const uint m_regionWidth = Constants.RegionSize; | 171 | private const uint m_regionWidth = Constants.RegionSize; |
@@ -345,9 +380,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
345 | private OdePrim cp1; | 380 | private OdePrim cp1; |
346 | private OdeCharacter cc2; | 381 | private OdeCharacter cc2; |
347 | private OdePrim cp2; | 382 | private OdePrim cp2; |
348 | private int tickCountFrameRun; | ||
349 | |||
350 | private int latertickcount=0; | ||
351 | //private int cStartStop = 0; | 383 | //private int cStartStop = 0; |
352 | //private string cDictKey = ""; | 384 | //private string cDictKey = ""; |
353 | 385 | ||
@@ -440,6 +472,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
440 | // Initialize the mesh plugin | 472 | // Initialize the mesh plugin |
441 | public override void Initialise(IMesher meshmerizer, IConfigSource config) | 473 | public override void Initialise(IMesher meshmerizer, IConfigSource config) |
442 | { | 474 | { |
475 | m_stats[ODENativeCollisionFrameMsStatName] = 0; | ||
476 | |||
443 | mesher = meshmerizer; | 477 | mesher = meshmerizer; |
444 | m_config = config; | 478 | m_config = config; |
445 | // Defaults | 479 | // Defaults |
@@ -464,6 +498,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
464 | IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; | 498 | IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; |
465 | if (physicsconfig != null) | 499 | if (physicsconfig != null) |
466 | { | 500 | { |
501 | CollectStats = physicsconfig.GetBoolean("collect_stats", false); | ||
502 | |||
467 | gravityx = physicsconfig.GetFloat("world_gravityx", 0f); | 503 | gravityx = physicsconfig.GetFloat("world_gravityx", 0f); |
468 | gravityy = physicsconfig.GetFloat("world_gravityy", 0f); | 504 | gravityy = physicsconfig.GetFloat("world_gravityy", 0f); |
469 | gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); | 505 | gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); |
@@ -765,6 +801,62 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
765 | #region Collision Detection | 801 | #region Collision Detection |
766 | 802 | ||
767 | /// <summary> | 803 | /// <summary> |
804 | /// Collides two geometries. | ||
805 | /// </summary> | ||
806 | /// <returns></returns> | ||
807 | /// <param name='geom1'></param> | ||
808 | /// <param name='geom2'>/param> | ||
809 | /// <param name='maxContacts'></param> | ||
810 | /// <param name='contactsArray'></param> | ||
811 | /// <param name='contactGeomSize'></param> | ||
812 | private int CollideGeoms( | ||
813 | IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize) | ||
814 | { | ||
815 | int count; | ||
816 | |||
817 | lock (OdeScene.UniversalColliderSyncObject) | ||
818 | { | ||
819 | // We do this inside the lock so that we don't count any delay in acquiring it | ||
820 | if (CollectStats) | ||
821 | m_nativeCollisionTickRecorder = Util.EnvironmentTickCount(); | ||
822 | |||
823 | count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize); | ||
824 | } | ||
825 | |||
826 | // We do this outside the lock so that any waiting threads aren't held up, though the effect is probably | ||
827 | // negligable | ||
828 | if (CollectStats) | ||
829 | m_stats[ODENativeCollisionFrameMsStatName] | ||
830 | += Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder); | ||
831 | |||
832 | return count; | ||
833 | } | ||
834 | |||
835 | /// <summary> | ||
836 | /// Collide two spaces or a space and a geometry. | ||
837 | /// </summary> | ||
838 | /// <param name='space1'></param> | ||
839 | /// <param name='space2'>/param> | ||
840 | /// <param name='data'></param> | ||
841 | private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data) | ||
842 | { | ||
843 | if (CollectStats) | ||
844 | { | ||
845 | m_inCollisionTiming = true; | ||
846 | m_nativeCollisionTickRecorder = Util.EnvironmentTickCount(); | ||
847 | } | ||
848 | |||
849 | d.SpaceCollide2(space1, space2, data, nearCallback); | ||
850 | |||
851 | if (CollectStats && m_inCollisionTiming) | ||
852 | { | ||
853 | m_stats[ODENativeCollisionFrameMsStatName] | ||
854 | += Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder); | ||
855 | m_inCollisionTiming = false; | ||
856 | } | ||
857 | } | ||
858 | |||
859 | /// <summary> | ||
768 | /// This is our near callback. A geometry is near a body | 860 | /// This is our near callback. A geometry is near a body |
769 | /// </summary> | 861 | /// </summary> |
770 | /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param> | 862 | /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param> |
@@ -772,6 +864,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
772 | /// <param name="g2">another geometry or space</param> | 864 | /// <param name="g2">another geometry or space</param> |
773 | private void near(IntPtr space, IntPtr g1, IntPtr g2) | 865 | private void near(IntPtr space, IntPtr g1, IntPtr g2) |
774 | { | 866 | { |
867 | if (CollectStats && m_inCollisionTiming) | ||
868 | { | ||
869 | m_stats[ODENativeCollisionFrameMsStatName] | ||
870 | += Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder); | ||
871 | m_inCollisionTiming = false; | ||
872 | } | ||
873 | |||
775 | // m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); | 874 | // m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); |
776 | // no lock here! It's invoked from within Simulate(), which is thread-locked | 875 | // no lock here! It's invoked from within Simulate(), which is thread-locked |
777 | 876 | ||
@@ -789,7 +888,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
789 | // contact points in the space | 888 | // contact points in the space |
790 | try | 889 | try |
791 | { | 890 | { |
792 | d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); | 891 | CollideSpaces(g1, g2, IntPtr.Zero); |
793 | } | 892 | } |
794 | catch (AccessViolationException) | 893 | catch (AccessViolationException) |
795 | { | 894 | { |
@@ -832,6 +931,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
832 | 931 | ||
833 | // Figure out how many contact points we have | 932 | // Figure out how many contact points we have |
834 | int count = 0; | 933 | int count = 0; |
934 | |||
835 | try | 935 | try |
836 | { | 936 | { |
837 | // Colliding Geom To Geom | 937 | // Colliding Geom To Geom |
@@ -843,8 +943,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
843 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) | 943 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) |
844 | return; | 944 | return; |
845 | 945 | ||
846 | lock (OdeScene.UniversalColliderSyncObject) | 946 | count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); |
847 | count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); | ||
848 | 947 | ||
849 | if (count > contacts.Length) | 948 | if (count > contacts.Length) |
850 | m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); | 949 | m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); |
@@ -1578,7 +1677,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1578 | // and we'll run it again on all of them. | 1677 | // and we'll run it again on all of them. |
1579 | try | 1678 | try |
1580 | { | 1679 | { |
1581 | d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); | 1680 | CollideSpaces(space, chr.Shell, IntPtr.Zero); |
1582 | } | 1681 | } |
1583 | catch (AccessViolationException) | 1682 | catch (AccessViolationException) |
1584 | { | 1683 | { |
@@ -1593,6 +1692,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1593 | //} | 1692 | //} |
1594 | } | 1693 | } |
1595 | 1694 | ||
1695 | // if (framecount % 55 == 0) | ||
1696 | // m_log.DebugFormat("Processed {0} collisions", _perloopContact.Count); | ||
1697 | |||
1596 | List<OdePrim> removeprims = null; | 1698 | List<OdePrim> removeprims = null; |
1597 | foreach (OdePrim chr in _activeprims) | 1699 | foreach (OdePrim chr in _activeprims) |
1598 | { | 1700 | { |
@@ -1604,7 +1706,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1604 | { | 1706 | { |
1605 | if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) | 1707 | if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) |
1606 | { | 1708 | { |
1607 | d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); | 1709 | CollideSpaces(space, chr.prim_geom, IntPtr.Zero); |
1608 | } | 1710 | } |
1609 | else | 1711 | else |
1610 | { | 1712 | { |
@@ -2689,7 +2791,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2689 | /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) | 2791 | /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) |
2690 | /// </summary> | 2792 | /// </summary> |
2691 | /// <param name="timeStep"></param> | 2793 | /// <param name="timeStep"></param> |
2692 | /// <returns></returns> | 2794 | /// <returns>The number of frames simulated over that period.</returns> |
2693 | public override float Simulate(float timeStep) | 2795 | public override float Simulate(float timeStep) |
2694 | { | 2796 | { |
2695 | if (framecount >= int.MaxValue) | 2797 | if (framecount >= int.MaxValue) |
@@ -3190,7 +3292,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3190 | public override bool IsThreaded | 3292 | public override bool IsThreaded |
3191 | { | 3293 | { |
3192 | // for now we won't be multithreaded | 3294 | // for now we won't be multithreaded |
3193 | get { return (false); } | 3295 | get { return false; } |
3194 | } | 3296 | } |
3195 | 3297 | ||
3196 | #region ODE Specific Terrain Fixes | 3298 | #region ODE Specific Terrain Fixes |
@@ -3955,5 +4057,22 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3955 | ds.SetViewpoint(ref xyz, ref hpr); | 4057 | ds.SetViewpoint(ref xyz, ref hpr); |
3956 | } | 4058 | } |
3957 | #endif | 4059 | #endif |
4060 | |||
4061 | public override Dictionary<string, float> GetStats() | ||
4062 | { | ||
4063 | if (!CollectStats) | ||
4064 | return null; | ||
4065 | |||
4066 | Dictionary<string, float> returnStats; | ||
4067 | |||
4068 | lock (OdeLock) | ||
4069 | { | ||
4070 | returnStats = new Dictionary<string, float>(m_stats); | ||
4071 | |||
4072 | m_stats[ODENativeCollisionFrameMsStatName] = 0; | ||
4073 | } | ||
4074 | |||
4075 | return returnStats; | ||
4076 | } | ||
3958 | } | 4077 | } |
3959 | } \ No newline at end of file | 4078 | } \ No newline at end of file |