aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-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
-rw-r--r--bin/OpenSimDefaults.ini30
6 files changed, 271 insertions, 71 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
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 5da3ba2..27d86e8 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -675,6 +675,25 @@
675 675
676 676
677[ODEPhysicsSettings] 677[ODEPhysicsSettings]
678 ; ##
679 ; ## Physics stats settings
680 ;
681
682 ; If collect_stats is enabled, then extra stat information is collected which is accessible via the MonitorModule
683 ; (see http://opensimulator.org/wiki/Monitoring_Module for more details).
684 collect_stats = false
685
686 ; ##
687 ; ## Physics logging settings - logfiles are saved to *.DIF files
688 ; ##
689
690 ; default is false
691 ;physics_logging = true
692 ;; every n simulation iterations, the physics snapshot file is updated
693 ;physics_logging_interval = 50
694 ;; append to existing physics logfile, or overwrite existing logfiles?
695 ;physics_logging_append_existing_logfile = true
696
678 ;## 697 ;##
679 ;## World Settings 698 ;## World Settings
680 ;## 699 ;##
@@ -824,17 +843,6 @@
824 mesh_physical_lod = 16 843 mesh_physical_lod = 16
825 844
826 ; ## 845 ; ##
827 ; ## Physics logging settings - logfiles are saved to *.DIF files
828 ; ##
829
830 ; default is false
831 ;physics_logging = true
832 ;; every n simulation iterations, the physics snapshot file is updated
833 ;physics_logging_interval = 50
834 ;; append to existing physics logfile, or overwrite existing logfiles?
835 ;physics_logging_append_existing_logfile = true
836
837 ; ##
838 ; ## Joint support 846 ; ## Joint support
839 ; ## 847 ; ##
840 848