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.
0.7.3-extended
Justin Clark-Casey (justincc) 2012-05-31 01:52:26 +01:00
parent 59a48d9ebb
commit 2fc461d9ab
6 changed files with 271 additions and 71 deletions

View File

@ -28,6 +28,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
@ -138,7 +139,7 @@ namespace OpenSim
m_log.Info("====================================================================");
m_log.Info("========================= STARTING OPENSIM =========================");
m_log.Info("====================================================================");
//m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString());
// http://msdn.microsoft.com/en-us/library/bb384202.aspx
//GCSettings.LatencyMode = GCLatencyMode.Batch;

View File

@ -49,7 +49,16 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public bool Enabled { get; private set; }
private Scene m_scene;
private readonly List<IMonitor> m_monitors = new List<IMonitor>();
/// <summary>
/// These are monitors where we know the static details in advance.
/// </summary>
/// <remarks>
/// Dynamic monitors also exist (we don't know any of the details of what stats we get back here)
/// but these are currently hardcoded.
/// </remarks>
private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>();
private readonly List<IAlert> m_alerts = new List<IAlert>();
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -84,9 +93,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public void DebugMonitors(string module, string[] args)
{
foreach (IMonitor monitor in m_monitors)
foreach (IMonitor monitor in m_staticMonitors)
{
m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue());
m_log.InfoFormat(
"[MONITOR MODULE]: {0} reports {1} = {2}",
m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
}
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
{
m_log.InfoFormat(
"[MONITOR MODULE]: {0} reports {1} = {2}",
m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
}
}
@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
{
string monID = (string) request["monitor"];
foreach (IMonitor monitor in m_monitors)
foreach (IMonitor monitor in m_staticMonitors)
{
string elemName = monitor.ToString();
if (elemName.StartsWith(monitor.GetType().Namespace))
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
if (elemName == monID || monitor.ToString() == monID)
{
Hashtable ereply3 = new Hashtable();
@ -123,6 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
}
}
// FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
// is even doing. Why are we inspecting the type of the monitor???
// No monitor with that name
Hashtable ereply2 = new Hashtable();
@ -134,12 +156,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
}
string xml = "<data>";
foreach (IMonitor monitor in m_monitors)
foreach (IMonitor monitor in m_staticMonitors)
{
string elemName = monitor.GetName();
xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
}
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
{
xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
}
xml += "</data>";
Hashtable ereply = new Hashtable();
@ -156,20 +184,20 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
if (!Enabled)
return;
m_monitors.Add(new AgentCountMonitor(m_scene));
m_monitors.Add(new ChildAgentCountMonitor(m_scene));
m_monitors.Add(new GCMemoryMonitor());
m_monitors.Add(new ObjectCountMonitor(m_scene));
m_monitors.Add(new PhysicsFrameMonitor(m_scene));
m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
m_monitors.Add(new PWSMemoryMonitor());
m_monitors.Add(new ThreadCountMonitor());
m_monitors.Add(new TotalFrameMonitor(m_scene));
m_monitors.Add(new EventFrameMonitor(m_scene));
m_monitors.Add(new LandFrameMonitor(m_scene));
m_monitors.Add(new LastFrameTimeMonitor(m_scene));
m_staticMonitors.Add(new AgentCountMonitor(m_scene));
m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
m_staticMonitors.Add(new GCMemoryMonitor());
m_staticMonitors.Add(new ObjectCountMonitor(m_scene));
m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene));
m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
m_staticMonitors.Add(new PWSMemoryMonitor());
m_staticMonitors.Add(new ThreadCountMonitor());
m_staticMonitors.Add(new TotalFrameMonitor(m_scene));
m_staticMonitors.Add(new EventFrameMonitor(m_scene));
m_staticMonitors.Add(new LandFrameMonitor(m_scene));
m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"TimeDilationMonitor",
@ -177,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[0],
m => m.GetValue().ToString()));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"SimFPSMonitor",
@ -185,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[1],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PhysicsFPSMonitor",
@ -193,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[2],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"AgentUpdatesPerSecondMonitor",
@ -201,15 +229,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[3],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
new GenericMonitor(
m_scene,
"ObjectUpdatesPerSecondMonitor",
"Object Updates",
m => m.Scene.StatsReporter.LastReportedObjectUpdates,
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ActiveObjectCountMonitor",
@ -217,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[7],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ActiveScriptsMonitor",
@ -225,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[19],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ScriptEventsPerSecondMonitor",
@ -233,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[20],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"InPacketsPerSecondMonitor",
@ -241,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[13],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"OutPacketsPerSecondMonitor",
@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[14],
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"UnackedBytesMonitor",
@ -257,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[15],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PendingDownloadsMonitor",
@ -265,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[17],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PendingUploadsMonitor",
@ -273,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[18],
m => string.Format("{0}", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"TotalFrameTimeMonitor",
@ -281,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[8],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"NetFrameTimeMonitor",
@ -289,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[9],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"PhysicsFrameTimeMonitor",
@ -297,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[10],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"SimulationFrameTimeMonitor",
@ -305,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[12],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"AgentFrameTimeMonitor",
@ -313,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[16],
m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add(
m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ImagesFrameTimeMonitor",
@ -321,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[11],
m => string.Format("{0} ms", m.GetValue())));
m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
foreach (IAlert alert in m_alerts)
{

View File

@ -26,7 +26,7 @@
*/
using System;
//using System.Collections.Generic;
using System.Collections.Generic;
using System.Timers;
using OpenMetaverse.Packets;
using OpenSim.Framework;
@ -35,10 +35,18 @@ using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.Framework.Scenes
{
/// <summary>
/// Collect statistics from the scene to send to the client and for access by other monitoring tools.
/// </summary>
/// <remarks>
/// FIXME: This should be a monitoring region module
/// </remarks>
public class SimStatsReporter
{
// private static readonly log4net.ILog m_log
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static readonly log4net.ILog m_log
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
public delegate void SendStatResult(SimStats stats);
@ -100,6 +108,14 @@ namespace OpenSim.Region.Framework.Scenes
get { return lastReportedSimStats; }
}
/// <summary>
/// Extra sim statistics that are used by monitors but not sent to the client.
/// </summary>
/// <value>
/// The keys are the stat names.
/// </value>
private Dictionary<string, float> m_lastReportedExtraSimStats = new Dictionary<string, float>();
// Sending a stats update every 3 seconds-
private int statsUpdatesEveryMS = 3000;
private float statsUpdateFactor = 0;
@ -328,7 +344,20 @@ namespace OpenSim.Region.Framework.Scenes
}
// Extra statistics that aren't currently sent to clients
LastReportedObjectUpdates = m_objectUpdates / statsUpdateFactor;
lock (m_lastReportedExtraSimStats)
{
m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / statsUpdateFactor;
Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
if (physicsStats != null)
{
foreach (KeyValuePair<string, float> tuple in physicsStats)
{
m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / statsUpdateFactor;
}
}
}
resetvalues();
}
@ -481,7 +510,10 @@ namespace OpenSim.Region.Framework.Scenes
public void AddPendingDownloads(int count)
{
m_pendingDownloads += count;
if (m_pendingDownloads < 0) m_pendingDownloads = 0;
if (m_pendingDownloads < 0)
m_pendingDownloads = 0;
//m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
}
@ -503,5 +535,11 @@ namespace OpenSim.Region.Framework.Scenes
}
#endregion
public Dictionary<string, float> GetExtraSimStats()
{
lock (m_lastReportedExtraSimStats)
return new Dictionary<string, float>(m_lastReportedExtraSimStats);
}
}
}

View File

@ -192,8 +192,22 @@ namespace OpenSim.Region.Physics.Manager
public abstract void AddPhysicsActorTaint(PhysicsActor prim);
/// <summary>
/// Perform a simulation of the current physics scene over the given timestep.
/// </summary>
/// <param name="timeStep"></param>
/// <returns>The number of frames simulated over that period.</returns>
public abstract float Simulate(float timeStep);
/// <summary>
/// Get statistics about this scene.
/// </summary>
/// <remarks>This facility is currently experimental and subject to change.</remarks>
/// <returns>
/// A dictionary where the key is the statistic name. If no statistics are supplied then returns null.
/// </returns>
public virtual Dictionary<string, float> GetStats() { return null; }
public abstract void GetResults();
public abstract void SetTerrain(float[] heightMap);

View File

@ -131,6 +131,41 @@ namespace OpenSim.Region.Physics.OdePlugin
/// </remarks>
internal static Object UniversalColliderSyncObject = new Object();
/// <summary>
/// Is stats collecting enabled for this ODE scene?
/// </summary>
public bool CollectStats { get; set; }
/// <summary>
/// Statistics for this scene.
/// </summary>
private Dictionary<string, float> m_stats = new Dictionary<string, float>();
/// <summary>
/// Stat name for recording the number of milliseconds that ODE spends in native collision code.
/// </summary>
public const string ODENativeCollisionFrameMsStatName = "ODENativeCollisionFrameMS";
/// <summary>
/// Used to hold tick numbers for stat collection purposes.
/// </summary>
private int m_nativeCollisionTickRecorder;
/// <summary>
/// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback.
/// </summary>
private bool m_inCollisionTiming;
/// <summary>
/// Used in calculating physics frame time dilation
/// </summary>
private int tickCountFrameRun;
/// <summary>
/// Used in calculating physics frame time dilation
/// </summary>
private int latertickcount;
private Random fluidRandomizer = new Random(Environment.TickCount);
private const uint m_regionWidth = Constants.RegionSize;
@ -345,9 +380,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private OdePrim cp1;
private OdeCharacter cc2;
private OdePrim cp2;
private int tickCountFrameRun;
private int latertickcount=0;
//private int cStartStop = 0;
//private string cDictKey = "";
@ -440,6 +472,8 @@ namespace OpenSim.Region.Physics.OdePlugin
// Initialize the mesh plugin
public override void Initialise(IMesher meshmerizer, IConfigSource config)
{
m_stats[ODENativeCollisionFrameMsStatName] = 0;
mesher = meshmerizer;
m_config = config;
// Defaults
@ -464,6 +498,8 @@ namespace OpenSim.Region.Physics.OdePlugin
IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
if (physicsconfig != null)
{
CollectStats = physicsconfig.GetBoolean("collect_stats", false);
gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
@ -764,6 +800,62 @@ namespace OpenSim.Region.Physics.OdePlugin
#region Collision Detection
/// <summary>
/// Collides two geometries.
/// </summary>
/// <returns></returns>
/// <param name='geom1'></param>
/// <param name='geom2'>/param>
/// <param name='maxContacts'></param>
/// <param name='contactsArray'></param>
/// <param name='contactGeomSize'></param>
private int CollideGeoms(
IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize)
{
int count;
lock (OdeScene.UniversalColliderSyncObject)
{
// We do this inside the lock so that we don't count any delay in acquiring it
if (CollectStats)
m_nativeCollisionTickRecorder = Util.EnvironmentTickCount();
count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize);
}
// We do this outside the lock so that any waiting threads aren't held up, though the effect is probably
// negligable
if (CollectStats)
m_stats[ODENativeCollisionFrameMsStatName]
+= Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder);
return count;
}
/// <summary>
/// Collide two spaces or a space and a geometry.
/// </summary>
/// <param name='space1'></param>
/// <param name='space2'>/param>
/// <param name='data'></param>
private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data)
{
if (CollectStats)
{
m_inCollisionTiming = true;
m_nativeCollisionTickRecorder = Util.EnvironmentTickCount();
}
d.SpaceCollide2(space1, space2, data, nearCallback);
if (CollectStats && m_inCollisionTiming)
{
m_stats[ODENativeCollisionFrameMsStatName]
+= Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder);
m_inCollisionTiming = false;
}
}
/// <summary>
/// This is our near callback. A geometry is near a body
/// </summary>
@ -772,6 +864,13 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <param name="g2">another geometry or space</param>
private void near(IntPtr space, IntPtr g1, IntPtr g2)
{
if (CollectStats && m_inCollisionTiming)
{
m_stats[ODENativeCollisionFrameMsStatName]
+= Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder);
m_inCollisionTiming = false;
}
// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space);
// no lock here! It's invoked from within Simulate(), which is thread-locked
@ -789,7 +888,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// contact points in the space
try
{
d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
CollideSpaces(g1, g2, IntPtr.Zero);
}
catch (AccessViolationException)
{
@ -832,6 +931,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// Figure out how many contact points we have
int count = 0;
try
{
// Colliding Geom To Geom
@ -843,8 +943,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
return;
lock (OdeScene.UniversalColliderSyncObject)
count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
if (count > contacts.Length)
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
// and we'll run it again on all of them.
try
{
d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
CollideSpaces(space, chr.Shell, IntPtr.Zero);
}
catch (AccessViolationException)
{
@ -1593,6 +1692,9 @@ namespace OpenSim.Region.Physics.OdePlugin
//}
}
// if (framecount % 55 == 0)
// m_log.DebugFormat("Processed {0} collisions", _perloopContact.Count);
List<OdePrim> removeprims = null;
foreach (OdePrim chr in _activeprims)
{
@ -1604,7 +1706,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
{
d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
CollideSpaces(space, chr.prim_geom, IntPtr.Zero);
}
else
{
@ -2689,7 +2791,7 @@ namespace OpenSim.Region.Physics.OdePlugin
/// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
/// </summary>
/// <param name="timeStep"></param>
/// <returns></returns>
/// <returns>The number of frames simulated over that period.</returns>
public override float Simulate(float timeStep)
{
if (framecount >= int.MaxValue)
@ -3190,7 +3292,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public override bool IsThreaded
{
// for now we won't be multithreaded
get { return (false); }
get { return false; }
}
#region ODE Specific Terrain Fixes
@ -3955,5 +4057,22 @@ namespace OpenSim.Region.Physics.OdePlugin
ds.SetViewpoint(ref xyz, ref hpr);
}
#endif
public override Dictionary<string, float> GetStats()
{
if (!CollectStats)
return null;
Dictionary<string, float> returnStats;
lock (OdeLock)
{
returnStats = new Dictionary<string, float>(m_stats);
m_stats[ODENativeCollisionFrameMsStatName] = 0;
}
return returnStats;
}
}
}

View File

@ -658,6 +658,25 @@
[ODEPhysicsSettings]
; ##
; ## Physics stats settings
;
; If collect_stats is enabled, then extra stat information is collected which is accessible via the MonitorModule
; (see http://opensimulator.org/wiki/Monitoring_Module for more details).
collect_stats = false
; ##
; ## Physics logging settings - logfiles are saved to *.DIF files
; ##
; default is false
;physics_logging = true
;; every n simulation iterations, the physics snapshot file is updated
;physics_logging_interval = 50
;; append to existing physics logfile, or overwrite existing logfiles?
;physics_logging_append_existing_logfile = true
;##
;## World Settings
;##
@ -806,17 +825,6 @@
; number^2 physical level of detail of the sculpt texture. 16x16 - 256 verticies
mesh_physical_lod = 16
; ##
; ## Physics logging settings - logfiles are saved to *.DIF files
; ##
; default is false
;physics_logging = true
;; every n simulation iterations, the physics snapshot file is updated
;physics_logging_interval = 50
;; append to existing physics logfile, or overwrite existing logfiles?
;physics_logging_append_existing_logfile = true
; ##
; ## Joint support
; ##