]> git.tdb.fi Git - libs/core.git/blobdiff - source/debug/profiler.cpp
Add Debug::Profiler
[libs/core.git] / source / debug / profiler.cpp
diff --git a/source/debug/profiler.cpp b/source/debug/profiler.cpp
new file mode 100644 (file)
index 0000000..4251797
--- /dev/null
@@ -0,0 +1,96 @@
+/* $Id$
+
+This file is part of libmspcore
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "../core/except.h"
+#include "../time/units.h"
+#include "profiler.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Debug {
+
+Profiler::Profiler():
+       period(0),
+       inner(0)
+{ }
+
+void Profiler::set_period(unsigned p)
+{
+       if(p==period)
+               return;
+
+       period=p;
+       for(map<string, ScopeInfo>::iterator i=scopes.begin(); i!=scopes.end(); ++i)
+       {
+               ScopeInfo &si=i->second;
+               if(p==0)
+                       si.history.clear();
+               else
+                       si.history.assign(period, Time::zero);
+               si.hist_pos=0;
+       }
+}
+
+void Profiler::add_scope(const std::string &name)
+{
+       if(!scopes.count(name))
+       {
+               map<string, ScopeInfo>::iterator i=scopes.insert(map<string, ScopeInfo>::value_type(name, ScopeInfo())).first;
+               i->second.history.resize(period);
+       }
+}
+
+ProfilingScope *Profiler::enter(ProfilingScope *ps)
+{
+       ProfilingScope *old=inner;
+       inner=ps;
+       return old;
+}
+
+void Profiler::record(const string &scope_name, const string &parent, const Time::TimeDelta &time, const Time::TimeDelta &child_t)
+{
+       map<string, ScopeInfo>::iterator i=scopes.find(scope_name);
+       if(i==scopes.end())
+       {
+               i=scopes.insert(map<string, ScopeInfo>::value_type(scope_name, ScopeInfo())).first;
+               i->second.history.resize(period);
+       }
+
+       ScopeInfo &si=i->second;
+       ++si.calls;
+       ++si.called_from[parent];
+       si.total_time+=time;
+       si.self_time+=time-child_t;
+       if(period)
+       {
+               si.avg_time+=(time-si.history[si.hist_pos])/period;
+               si.history[si.hist_pos++]=time;
+               if(si.hist_pos>=period)
+                       si.hist_pos-=period;
+       }
+       else
+               si.avg_time=si.total_time/si.calls;
+}
+
+const Profiler::ScopeInfo &Profiler::scope(const string &sn) const
+{
+       map<string, ScopeInfo>::const_iterator i=scopes.find(sn);
+       if(i==scopes.end())
+               throw KeyError("Unknown scope");
+
+       return i->second;
+}
+
+
+Profiler::ScopeInfo::ScopeInfo():
+       calls(0),
+       hist_pos(0)
+{ }
+
+} // namespace Debug
+} // namespace Msp