diff options
author | Justin Clark-Casey (justincc) | 2012-05-31 01:52:26 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-05-31 01:52:26 +0100 |
commit | 0b02a4d42e989609a4e1ba39d2aee9a7f9655613 (patch) | |
tree | 353e05997fb8478cb6b3691edc943604e5dd78ff /OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |
parent | Add console command "teleport user" to allow teleport from the region console (diff) | |
download | opensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.zip opensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.gz opensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.bz2 opensim-SC_OLD-0b02a4d42e989609a4e1ba39d2aee9a7f9655613.tar.xz |
Add an optional mechanism for physics modules to collect and return arbitrary stats.
If active, the physics module can return arbitrary stat counters that can be seen via the MonitoringModule
(http://opensimulator.org/wiki/Monitoring_Module)
This is only active in OdeScene if collect_stats = true in [ODEPhysicsSettings].
This patch allows OdeScene to collect elapsed time information for calls to the ODE native collision methods to assess what proportion of time this takes compared to total physics processing.
This data is returned as ODENativeCollisionFrameMS in the monitoring module, updated every 3 seconds.
The performance effect of collecting stats is probably extremely minor, dwarfed by the rest of the physics code.
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/OdeScene.cs')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 139 |
1 files changed, 129 insertions, 10 deletions
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 |