diff options
-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 | ||||
-rw-r--r-- | bin/OpenSimDefaults.ini | 30 |
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 @@ | |||
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 |
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 | ||