aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-05-31 01:52:26 +0100
committerJustin Clark-Casey (justincc)2012-05-31 01:52:26 +0100
commit0b02a4d42e989609a4e1ba39d2aee9a7f9655613 (patch)
tree353e05997fb8478cb6b3691edc943604e5dd78ff /OpenSim/Region
parentAdd console command "teleport user" to allow teleport from the region console (diff)
downloadopensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.zip
opensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.gz
opensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.bz2
opensim-SC_OLD-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.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs108
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs48
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs14
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs139
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 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics;
31using System.IO; 32using System.IO;
32using System.Reflection; 33using System.Reflection;
33using System.Text; 34using 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
28using System; 28using System;
29//using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
32using OpenSim.Framework; 32using OpenSim.Framework;
@@ -35,10 +35,18 @@ using OpenSim.Region.Framework.Interfaces;
35 35
36namespace OpenSim.Region.Framework.Scenes 36namespace 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