]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/subsystem_mgr.cxx
Merge branch 'master' of git://gitorious.org/fg/simgear into fredb/winbuild
[simgear.git] / simgear / structure / subsystem_mgr.cxx
index 8b1d5ea456309e1b99134f88ae43c73016bbe420..ee9c15d1750dab1ab90d5e02b1612f1a4712fa1d 100644 (file)
@@ -1,9 +1,12 @@
 
 #include <simgear/debug/logstream.hxx>
+#include <simgear/timing/timestamp.hxx>
 
 #include "exception.hxx"
 #include "subsystem_mgr.hxx"
 
+#include <simgear/math/SGMath.hxx>
+
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -25,6 +28,11 @@ SGSubsystem::init ()
 {
 }
 
+void
+SGSubsystem::postinit ()
+{
+}
+
 void
 SGSubsystem::reinit ()
 {
@@ -65,6 +73,32 @@ SGSubsystem::is_suspended () const
 }
 
 
+void
+SGSubsystem::printTimingInformation ()
+{
+   SGTimeStamp startTime;
+   for ( eventTimeVecIterator i = timingInfo.begin();
+          i != timingInfo.end();
+          i++) {
+       if (i == timingInfo.begin()) {
+           startTime = i->getTime();
+       } else {
+           SGTimeStamp endTime = i->getTime();
+           SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp :   "
+                  << i->getName() << " takes " << endTime - startTime
+                  << " sec.");
+          startTime = endTime;
+       }
+   }
+}
+
+
+
+void SGSubsystem::stamp(const string& name)
+{
+    timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
+}
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystemGroup.
@@ -76,8 +110,12 @@ SGSubsystemGroup::SGSubsystemGroup ()
 
 SGSubsystemGroup::~SGSubsystemGroup ()
 {
-    for (unsigned int i = 0; i < _members.size(); i++)
-        delete _members[i];
+    // reverse order to prevent order dependency problems
+    for (unsigned int i = _members.size(); i > 0; i--)
+    {
+        _members[i-1]->printTimingStatistics();
+        delete _members[i-1];
+    }
 }
 
 void
@@ -87,6 +125,13 @@ SGSubsystemGroup::init ()
         _members[i]->subsystem->init();
 }
 
+void
+SGSubsystemGroup::postinit ()
+{
+    for (unsigned int i = 0; i < _members.size(); i++)
+        _members[i]->subsystem->postinit();
+}
+
 void
 SGSubsystemGroup::reinit ()
 {
@@ -104,15 +149,35 @@ SGSubsystemGroup::bind ()
 void
 SGSubsystemGroup::unbind ()
 {
-    for (unsigned int i = 0; i < _members.size(); i++)
-        _members[i]->subsystem->unbind();
+    // reverse order to prevent order dependency problems
+    for (unsigned int i = _members.size(); i > 0; i--)
+       _members[i-1]->subsystem->unbind();
 }
 
 void
 SGSubsystemGroup::update (double delta_time_sec)
 {
     for (unsigned int i = 0; i < _members.size(); i++)
-        _members[i]->update(delta_time_sec); // indirect call
+    {
+         SGTimeStamp timeStamp = SGTimeStamp::now();
+         _members[i]->update(delta_time_sec); // indirect call
+         timeStamp = timeStamp - SGTimeStamp::now();
+         double b = timeStamp.toUSecs();
+         _members[i]->updateExecutionTime(b);
+         double threshold = _members[i]->getTimeWarningThreshold();
+         if (( b > threshold ) && (b > 10000)) {
+             _members[i]->printTimingInformation(b);
+         }
+    }
+}
+
+void 
+SGSubsystemGroup::collectDebugTiming(bool collect)
+{
+    for (unsigned int i = 0; i < _members.size(); i++)
+    {
+        _members[i]->collectDebugTiming(collect);
+    }
 }
 
 void
@@ -168,6 +233,26 @@ SGSubsystemGroup::remove_subsystem (const string &name)
     }
 }
 
+void
+SGSubsystemGroup::Member::printTimingStatistics ()
+{
+    if (collectTimeStats) {
+        double minTime = timeStat.min()   / 1000;
+        double maxTime = timeStat.max()   / 1000;
+        double meanTime = timeStat.mean() / 1000;
+        double stddev   = timeStat.stdDev()   / 1000;
+
+        char buffer[256];
+        snprintf(buffer, 256, "Timing summary for %20s.\n"
+                              "-  mean time: %04.2f ms.\n"
+                              "-  min time : %04.2f ms.\n"
+                              "-  max time : %04.2f ms.\n"
+                              "- stddev    : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
+        SG_LOG(SG_GENERAL, SG_ALERT, buffer);
+    }
+}
+
+
 bool
 SGSubsystemGroup::has_subsystem (const string &name) const
 {
@@ -201,19 +286,19 @@ SGSubsystemGroup::Member::Member ()
     : name(""),
       subsystem(0),
       min_step_sec(0),
-      elapsed_sec(0)
+      elapsed_sec(0),
+      collectTimeStats(false)
 {
 }
 
+// This shouldn't be called due to subsystem pointer ownership issues.
 SGSubsystemGroup::Member::Member (const Member &)
 {
-    Member();
 }
 
 SGSubsystemGroup::Member::~Member ()
 {
-                                // FIXME: causes a crash
-//     delete subsystem;
+    delete subsystem;
 }
 
 void
@@ -229,6 +314,30 @@ SGSubsystemGroup::Member::update (double delta_time_sec)
 }
 
 
+void 
+SGSubsystemGroup::Member::printTimingInformation(double time)
+{
+     if (collectTimeStats) {
+         SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
+         subsystem->printTimingInformation();
+     }
+}
+
+double SGSubsystemGroup::Member::getTimeWarningThreshold()
+{
+    return (timeStat.mean() + 3 * timeStat.stdDev());
+}
+
+void SGSubsystemGroup::Member::updateExecutionTime(double time)
+{
+    if (collectTimeStats) {
+        timeStat += time;
+    }
+}
+
+
+
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystemMgr.
@@ -250,6 +359,13 @@ SGSubsystemMgr::init ()
             _groups[i].init();
 }
 
+void
+SGSubsystemMgr::postinit ()
+{
+    for (int i = 0; i < MAX_GROUPS; i++)
+            _groups[i].postinit();
+}
+
 void
 SGSubsystemMgr::reinit ()
 {
@@ -267,7 +383,8 @@ SGSubsystemMgr::bind ()
 void
 SGSubsystemMgr::unbind ()
 {
-    for (int i = 0; i < MAX_GROUPS; i++)
+    // reverse order to prevent order dependency problems
+    for (int i = MAX_GROUPS-1; i >= 0; i--)
         _groups[i].unbind();
 }
 
@@ -279,6 +396,14 @@ SGSubsystemMgr::update (double delta_time_sec)
     }
 }
 
+void 
+SGSubsystemMgr::collectDebugTiming(bool collect)
+{
+    for (int i = 0; i < MAX_GROUPS; i++) {
+        _groups[i].collectDebugTiming(collect);
+    }
+}
+
 void
 SGSubsystemMgr::suspend ()
 {