PageRenderTime 28ms CodeModel.GetById 16ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 0ms

/Aurora/Modules/World/Sim Protection/PhysicsMonitor.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 375 lines | 303 code | 35 blank | 37 comment | 28 complexity | 9568e2ed1153a9c4c79b455f93eb19a9 MD5 | raw file
  1/*
  2 * Copyright (c) Contributors, http://aurora-sim.org/
  3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions are met:
  7 *     * Redistributions of source code must retain the above copyright
  8 *       notice, this list of conditions and the following disclaimer.
  9 *     * Redistributions in binary form must reproduce the above copyright
 10 *       notice, this list of conditions and the following disclaimer in the
 11 *       documentation and/or other materials provided with the distribution.
 12 *     * Neither the name of the Aurora-Sim Project nor the
 13 *       names of its contributors may be used to endorse or promote products
 14 *       derived from this software without specific prior written permission.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 */
 27
 28using Aurora.Framework;
 29using Aurora.Framework.ConsoleFramework;
 30using Aurora.Framework.Modules;
 31using Aurora.Framework.Physics;
 32using Aurora.Framework.SceneInfo;
 33using Aurora.Framework.Utilities;
 34using Nini.Config;
 35using OpenMetaverse;
 36using System;
 37using System.Collections.Generic;
 38using System.Threading;
 39using System.Timers;
 40using System.Windows.Forms;
 41using Timer = System.Timers.Timer;
 42
 43namespace Aurora.Modules.SimProtection
 44{
 45    public class PhysicsMonitor : INonSharedRegionModule, IPhysicsMonitor
 46    {
 47        #region Private class
 48
 49        protected class PhysicsStats
 50        {
 51            public float StatAvatarUpdatePosAndVelocity;
 52            public float StatCollisionAccountingTime;
 53            public float StatCollisionOptimizedTime;
 54            public float StatContactLoopTime;
 55            public float StatFindContactsTime;
 56            public float StatPhysicsMoveTime;
 57            public float StatPhysicsTaintTime;
 58            public float StatPrimUpdatePosAndVelocity;
 59            public float StatSendCollisionsTime;
 60            public float StatUnlockedArea;
 61        }
 62
 63        #endregion
 64
 65        #region Declares
 66
 67        public bool m_collectingStats;
 68
 69        protected Dictionary<UUID, PhysicsStats> m_currentPhysicsStats = new Dictionary<UUID, PhysicsStats>();
 70        protected Dictionary<UUID, PhysicsStats> m_lastPhysicsStats = new Dictionary<UUID, PhysicsStats>();
 71        protected DateTime m_lastUpdated = DateTime.Now;
 72        protected Timer m_physicsStatTimer;
 73        protected IScene m_Scene;
 74        protected int m_waitingForCollectionOfStats;
 75
 76        #endregion
 77
 78        #region IPhysicsMonitor Members
 79
 80        public virtual void AddPhysicsStats(UUID RegionID, PhysicsScene scene)
 81        {
 82            if (!m_collectingStats)
 83                return;
 84            lock (m_currentPhysicsStats)
 85            {
 86                PhysicsStats stats;
 87                if (!m_currentPhysicsStats.TryGetValue(RegionID, out stats))
 88                {
 89                    stats = new PhysicsStats
 90                                {
 91                                    StatAvatarUpdatePosAndVelocity = scene.StatAvatarUpdatePosAndVelocity,
 92                                    StatCollisionOptimizedTime = scene.StatCollisionOptimizedTime,
 93                                    StatPhysicsMoveTime = scene.StatPhysicsMoveTime,
 94                                    StatPhysicsTaintTime = scene.StatPhysicsTaintTime,
 95                                    StatPrimUpdatePosAndVelocity = scene.StatPrimUpdatePosAndVelocity,
 96                                    StatSendCollisionsTime = scene.StatSendCollisionsTime,
 97                                    StatUnlockedArea = scene.StatUnlockedArea,
 98                                    StatFindContactsTime = scene.StatFindContactsTime,
 99                                    StatContactLoopTime = scene.StatContactLoopTime,
100                                    StatCollisionAccountingTime = scene.StatCollisionAccountingTime
101                                };
102                }
103                else
104                {
105                    stats.StatAvatarUpdatePosAndVelocity += scene.StatAvatarUpdatePosAndVelocity;
106                    stats.StatCollisionOptimizedTime += scene.StatCollisionOptimizedTime;
107                    stats.StatPhysicsMoveTime += scene.StatPhysicsMoveTime;
108                    stats.StatPhysicsTaintTime += scene.StatPhysicsTaintTime;
109                    stats.StatPrimUpdatePosAndVelocity += scene.StatPrimUpdatePosAndVelocity;
110                    stats.StatSendCollisionsTime += scene.StatSendCollisionsTime;
111                    stats.StatUnlockedArea += scene.StatUnlockedArea;
112                    stats.StatFindContactsTime += scene.StatFindContactsTime;
113                    stats.StatContactLoopTime += scene.StatContactLoopTime;
114                    stats.StatCollisionAccountingTime += scene.StatCollisionAccountingTime;
115                }
116
117                m_currentPhysicsStats[RegionID] = stats;
118
119                PhysicsStats ProfilerStats = new PhysicsStats
120                                                 {
121                                                     StatAvatarUpdatePosAndVelocity =
122                                                         scene.StatAvatarUpdatePosAndVelocity,
123                                                     StatCollisionOptimizedTime = scene.StatCollisionOptimizedTime,
124                                                     StatPhysicsMoveTime = scene.StatPhysicsMoveTime,
125                                                     StatPhysicsTaintTime = scene.StatPhysicsTaintTime,
126                                                     StatPrimUpdatePosAndVelocity = scene.StatPrimUpdatePosAndVelocity,
127                                                     StatSendCollisionsTime = scene.StatSendCollisionsTime,
128                                                     StatUnlockedArea = scene.StatUnlockedArea,
129                                                     StatFindContactsTime = scene.StatFindContactsTime,
130                                                     StatContactLoopTime = scene.StatContactLoopTime,
131                                                     StatCollisionAccountingTime = scene.StatCollisionAccountingTime
132                                                 };
133
134                //Add the stats to the profiler
135                Profiler p = ProfilerManager.GetProfiler();
136                p.AddStat("CurrentStatAvatarUpdatePosAndVelocity " + RegionID,
137                          ProfilerStats.StatAvatarUpdatePosAndVelocity);
138                p.AddStat("CurrentStatCollisionOptimizedTime " + RegionID,
139                          ProfilerStats.StatCollisionOptimizedTime);
140                p.AddStat("CurrentStatPhysicsMoveTime " + RegionID,
141                          ProfilerStats.StatPhysicsMoveTime);
142                p.AddStat("CurrentStatPhysicsTaintTime " + RegionID,
143                          ProfilerStats.StatPhysicsTaintTime);
144                p.AddStat("CurrentStatPrimUpdatePosAndVelocity " + RegionID,
145                          ProfilerStats.StatPrimUpdatePosAndVelocity);
146                p.AddStat("CurrentStatSendCollisionsTime " + RegionID,
147                          ProfilerStats.StatSendCollisionsTime);
148                p.AddStat("CurrentStatUnlockedArea " + RegionID,
149                          ProfilerStats.StatUnlockedArea);
150                p.AddStat("CurrentStatFindContactsTime " + RegionID,
151                          ProfilerStats.StatFindContactsTime);
152                p.AddStat("CurrentStatContactLoopTime " + RegionID,
153                          ProfilerStats.StatContactLoopTime);
154                p.AddStat("CurrentStatCollisionAccountingTime " + RegionID,
155                          ProfilerStats.StatCollisionAccountingTime);
156            }
157        }
158
159        #endregion
160
161        #region INonSharedRegionModule Members
162
163        public string Name
164        {
165            get { return "PhysicsMonitor"; }
166        }
167
168        public Type ReplaceableInterface
169        {
170            get { return null; }
171        }
172
173        public void Initialise(IConfigSource source)
174        {
175            if (m_physicsStatTimer == null)
176            {
177                m_physicsStatTimer = new Timer {Interval = 10000};
178                m_physicsStatTimer.Elapsed += PhysicsStatsHeartbeat;
179            }
180        }
181
182        public void Close()
183        {
184        }
185
186        public void AddRegion(IScene scene)
187        {
188            m_Scene = scene;
189            scene.RegisterModuleInterface<IPhysicsMonitor>(this);
190            if (MainConsole.Instance != null)
191            {
192                MainConsole.Instance.Commands.AddCommand(
193                    "physics stats", "physics stats", "physics stats <region>", PhysicsStatsCommand);
194                MainConsole.Instance.Commands.AddCommand(
195                    "physics profiler", "physics profiler", "physics profiler <region>", PhysicsProfilerCommand);
196                MainConsole.Instance.Commands.AddCommand(
197                    "physics current stats", "physics current stats",
198                    "physics current stats <region> NOTE: these are not calculated and are in milliseconds per unknown time",
199                    CurrentPhysicsStatsCommand);
200            }
201        }
202
203        public void RemoveRegion(IScene scene)
204        {
205            m_Scene = null;
206            scene.UnregisterModuleInterface<IPhysicsMonitor>(this);
207        }
208
209        public void RegionLoaded(IScene scene)
210        {
211        }
212
213        #endregion
214
215        protected virtual void PhysicsStatsCommand(string[] cmd)
216        {
217            if (cmd.Length == 3)
218            {
219                if (m_Scene.RegionInfo.RegionName != cmd[2])
220                    return;
221            }
222
223            //Set all the bools to true
224            m_collectingStats = true;
225            m_waitingForCollectionOfStats = 1;
226            //Start the timer as well
227            m_physicsStatTimer.Start();
228            MainConsole.Instance.Info("Collecting Stats Now... Please wait...");
229            while (m_waitingForCollectionOfStats > 0)
230            {
231                Thread.Sleep(50);
232            }
233
234            PhysicsStats stats = null;
235            while (stats == null)
236            {
237                m_lastPhysicsStats.TryGetValue(m_Scene.RegionInfo.RegionID, out stats);
238            }
239            DumpStatsToConsole(m_Scene, stats);
240        }
241
242        protected virtual void PhysicsProfilerCommand(string[] cmd)
243        {
244            if (cmd.Length == 3)
245            {
246                if (m_Scene.RegionInfo.RegionName != cmd[2])
247                    return;
248            }
249
250            //Set all the bools to true
251            m_collectingStats = true;
252            m_waitingForCollectionOfStats = 1;
253            //Start the timer as well
254            m_physicsStatTimer.Start();
255            MainConsole.Instance.Info("Collecting Stats Now... Please wait...");
256            while (m_waitingForCollectionOfStats > 0)
257            {
258                Thread.Sleep(50);
259            }
260
261            Thread thread = new Thread(StartThread);
262            thread.Start(new List<IScene>() {m_Scene});
263        }
264
265        private void StartThread(object scenes)
266        {
267            Culture.SetCurrentCulture();
268            try
269            {
270                List<IScene> scenesToRun = (List<IScene>) scenes;
271                Application.Run(new PhysicsProfilerForm(this, scenesToRun));
272            }
273            catch (Exception ex)
274            {
275                MainConsole.Instance.Warn("There was an error opening the form: " + ex);
276            }
277        }
278
279        protected virtual void CurrentPhysicsStatsCommand(string[] cmd)
280        {
281            if (cmd.Length == 3)
282            {
283                if (m_Scene.RegionInfo.RegionName != cmd[2])
284                    return;
285            }
286
287            //Set all the bools to true
288            m_collectingStats = true;
289            m_waitingForCollectionOfStats = 1;
290            //Start the timer as well
291            m_physicsStatTimer.Start();
292            MainConsole.Instance.Info("Collecting Stats Now... Please wait...");
293            while (m_waitingForCollectionOfStats > 0)
294            {
295                Thread.Sleep(50);
296            }
297
298            PhysicsStats stats = null;
299            while (stats == null)
300            {
301                m_currentPhysicsStats.TryGetValue(m_Scene.RegionInfo.RegionID, out stats);
302            }
303            DumpStatsToConsole(m_Scene, stats);
304        }
305
306        protected virtual void DumpStatsToConsole(IScene scene, PhysicsStats stats)
307        {
308            MainConsole.Instance.Info("------  Physics Stats for region " + scene.RegionInfo.RegionName + "  ------");
309            MainConsole.Instance.Info("   All stats are in milliseconds spent per second.");
310            MainConsole.Instance.Info("   These are in the order they are run in the PhysicsScene.");
311            MainConsole.Instance.Info(" PhysicsTaintTime: " + stats.StatPhysicsTaintTime);
312            MainConsole.Instance.Info(" PhysicsMoveTime: " + stats.StatPhysicsMoveTime);
313            MainConsole.Instance.Info(" FindContactsTime: " + stats.StatFindContactsTime);
314            MainConsole.Instance.Info(" ContactLoopTime: " + stats.StatContactLoopTime);
315            MainConsole.Instance.Info(" CollisionAccountingTime: " + stats.StatCollisionAccountingTime);
316            MainConsole.Instance.Info(" CollisionOptimizedTime: " + stats.StatCollisionOptimizedTime);
317            MainConsole.Instance.Info(" SendCollisionsTime: " + stats.StatSendCollisionsTime);
318            MainConsole.Instance.Info(" AvatarUpdatePosAndVelocity: " + stats.StatAvatarUpdatePosAndVelocity);
319            MainConsole.Instance.Info(" PrimUpdatePosAndVelocity: " + stats.StatPrimUpdatePosAndVelocity);
320            MainConsole.Instance.Info(" UnlockedArea: " + stats.StatUnlockedArea);
321            MainConsole.Instance.Info("");
322        }
323
324        protected virtual void PhysicsStatsHeartbeat(object sender, ElapsedEventArgs e)
325        {
326            if (!m_collectingStats || m_currentPhysicsStats.Count == 0)
327                return;
328            lock (m_currentPhysicsStats)
329            {
330                foreach (KeyValuePair<UUID, PhysicsStats> kvp in m_currentPhysicsStats)
331                {
332                    //Save the stats in the last one so we can keep them for the console commands
333                    //Divide by 10 so we get per second
334                    m_lastPhysicsStats[kvp.Key] = kvp.Value;
335                    m_lastPhysicsStats[kvp.Key].StatAvatarUpdatePosAndVelocity /= 10;
336                    m_lastPhysicsStats[kvp.Key].StatCollisionOptimizedTime /= 10;
337                    m_lastPhysicsStats[kvp.Key].StatPhysicsMoveTime /= 10;
338                    m_lastPhysicsStats[kvp.Key].StatPhysicsTaintTime /= 10;
339                    m_lastPhysicsStats[kvp.Key].StatPrimUpdatePosAndVelocity /= 10;
340                    m_lastPhysicsStats[kvp.Key].StatSendCollisionsTime /= 10;
341                    m_lastPhysicsStats[kvp.Key].StatUnlockedArea /= 10;
342                    m_lastPhysicsStats[kvp.Key].StatFindContactsTime /= 10;
343                    m_lastPhysicsStats[kvp.Key].StatContactLoopTime /= 10;
344                    m_lastPhysicsStats[kvp.Key].StatCollisionAccountingTime /= 10;
345                    //Add the stats to the profiler
346                    Profiler p = ProfilerManager.GetProfiler();
347                    p.AddStat("StatAvatarUpdatePosAndVelocity " + kvp.Key,
348                              m_lastPhysicsStats[kvp.Key].StatAvatarUpdatePosAndVelocity);
349                    p.AddStat("StatCollisionOptimizedTime " + kvp.Key,
350                              m_lastPhysicsStats[kvp.Key].StatCollisionOptimizedTime);
351                    p.AddStat("StatPhysicsMoveTime " + kvp.Key,
352                              m_lastPhysicsStats[kvp.Key].StatPhysicsMoveTime);
353                    p.AddStat("StatPhysicsTaintTime " + kvp.Key,
354                              m_lastPhysicsStats[kvp.Key].StatPhysicsTaintTime);
355                    p.AddStat("StatPrimUpdatePosAndVelocity " + kvp.Key,
356                              m_lastPhysicsStats[kvp.Key].StatPrimUpdatePosAndVelocity);
357                    p.AddStat("StatSendCollisionsTime " + kvp.Key,
358                              m_lastPhysicsStats[kvp.Key].StatSendCollisionsTime);
359                    p.AddStat("StatUnlockedArea " + kvp.Key,
360                              m_lastPhysicsStats[kvp.Key].StatUnlockedArea);
361                    p.AddStat("StatFindContactsTime " + kvp.Key,
362                              m_lastPhysicsStats[kvp.Key].StatFindContactsTime);
363                    p.AddStat("StatContactLoopTime " + kvp.Key,
364                              m_lastPhysicsStats[kvp.Key].StatContactLoopTime);
365                    p.AddStat("StatCollisionAccountingTime " + kvp.Key,
366                              m_lastPhysicsStats[kvp.Key].StatCollisionAccountingTime);
367                }
368                m_currentPhysicsStats.Clear();
369            }
370            m_lastUpdated = DateTime.Now;
371            //If there are stats waiting, we just pulled them
372            m_waitingForCollectionOfStats--;
373        }
374    }
375}