00001
00011 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00012 #pragma once
00013 #endif
00014 #ifndef COMMON_PROFILER_H_
00015 #define COMMON_PROFILER_H_
00016
00017 #include <stack>
00018 #include <map>
00019 #include "DateTime.hpp"
00020 #include "Threads.hpp"
00021
00022 namespace common
00023 {
00024
00029
00030 class Profiler;
00031
00032 enum PROFILER_UNITS {
00033 PROFILER_UNITS_MILLISECONDS,
00034 PROFILER_UNITS_SECONDS,
00035 };
00036
00038 class ProfilerItem
00039 {
00040 private:
00041
00042 GameTime m_Time;
00043
00044 uint m_Count;
00045
00046 GameTime m_StartTime;
00047 tstring m_strName;
00048 std::vector<ProfilerItem> m_ItemVector;
00049
00050 friend class Profiler;
00051 ProfilerItem * Begin(const tstring &Name);
00052 void Start() { m_StartTime = GetCurrentGameTime(); }
00053 void Stop() { m_Time += GetCurrentGameTime() - m_StartTime; m_Count++; }
00054
00055 public:
00056 ProfilerItem(const tstring &Name);
00057
00058 const tstring &GetName() { return m_strName; }
00059 bool Empty() { return m_Count == 0; }
00060 uint GetCount() { return m_Count; }
00061 GameTime GetAvgTime() { return Empty() ? GameTime::ZERO : (m_Time / (int8)m_Count); }
00062 size_t GetItemCount() { return m_ItemVector.size(); }
00063 ProfilerItem* GetItem(size_t index) { return &m_ItemVector[index]; }
00064 void FormatString(tstring *S, unsigned dwLevel, PROFILER_UNITS units);
00065 };
00066
00068 class Profiler
00069 {
00070 public:
00071 Profiler();
00072 Profiler(const tstring &Name);
00073 void Begin(const tstring &Name);
00074 void End();
00075 ProfilerItem* GetRootItem() { return &m_DefaultItem; }
00077
00080 void FormatString(tstring *S, PROFILER_UNITS units);
00081
00082 private:
00083 std::stack<ProfilerItem*> m_ItemStack;
00084 ProfilerItem m_DefaultItem;
00085 };
00086
00088
00093 class Profile
00094 {
00095 private:
00096 Profiler &m_Profiler;
00097 public:
00098 Profile(Profiler &profiler, const tstring &Name);
00099 ~Profile();
00100 };
00101
00103
00108 template < typename KeyT, typename KeyTraits=std::less<KeyT> >
00109 class FlatProfiler
00110 {
00111 public:
00112 FlatProfiler() : m_Mutex(0) { }
00114 void Clear();
00116 void AddSample(const KeyT &key, GameTime timeInterval);
00118 void FormatString(tstring *out, PROFILER_UNITS units);
00119
00120 private:
00121 struct ENTRY
00122 {
00123 GameTime SumTime;
00124 uint Count;
00125 ENTRY() : SumTime(GameTime::ZERO), Count(0) { }
00126 GameTime GetAvgTime() const { return SumTime / (int8)Count; }
00127 };
00128 typedef std::map<KeyT, ENTRY, KeyTraits> MapType;
00129
00130 Mutex m_Mutex;
00131 MapType m_Entries;
00132 };
00133
00135
00137 template < typename KeyT, typename KeyTraits=std::less<KeyT> >
00138 class FlatProfilerSampler
00139 {
00140 public:
00141 FlatProfilerSampler(FlatProfiler<KeyT, KeyTraits> &profiler, const KeyT &key) : m_Profiler(profiler), m_Key(key), m_StartTime(GetCurrentGameTime()) { }
00142 ~FlatProfilerSampler() { m_Profiler.AddSample(m_Key, GetCurrentGameTime() - m_StartTime); }
00143
00144 private:
00145 FlatProfiler<KeyT, KeyTraits> &m_Profiler;
00146 KeyT m_Key;
00147 GameTime m_StartTime;
00148 };
00149
00150 template <typename KeyT, typename KeyTraits>
00151 void FlatProfiler<KeyT, KeyTraits>::Clear()
00152 {
00153 MutexLock lock(m_Mutex);
00154 m_Entries.clear();
00155 }
00156
00157 template <typename KeyT, typename KeyTraits>
00158 void FlatProfiler<KeyT, KeyTraits>::AddSample(const KeyT &key, GameTime timeInterval)
00159 {
00160 MutexLock lock(m_Mutex);
00161 ENTRY &entry = m_Entries[key];
00162 entry.SumTime += timeInterval;
00163 entry.Count++;
00164 }
00165
00166 template <typename KeyT, typename KeyTraits>
00167 void FlatProfiler<KeyT, KeyTraits>::FormatString(tstring *out, PROFILER_UNITS units)
00168 {
00169 MutexLock lock(m_Mutex);
00170
00171 tstring keyStr;
00172 for (MapType::iterator it = m_Entries.begin(); it != m_Entries.end(); ++it)
00173 {
00174 const ENTRY &entry = it->second;
00175
00176 SthToStr<KeyT>(&keyStr, it->first);
00177 *out += keyStr;
00178 *out += _T(" : ");
00179
00180 if (units == PROFILER_UNITS_MILLISECONDS)
00181 {
00182 *out += DoubleToStrR(entry.GetAvgTime().ToSeconds_d()*1000.);
00183 *out += _T(" ms (");
00184 }
00185 else
00186 {
00187 *out += DoubleToStrR(entry.GetAvgTime().ToSeconds_d());
00188 *out += _T(" s (");
00189 }
00190 *out += UintToStrR(entry.Count);
00191 *out += _T(")\n");
00192 }
00193 }
00194
00196
00197
00198 }
00199
00205 #define PROFILE_GUARD(profiler,Name) common::Profile __profile_guard_object(profiler, Name);
00206
00207
00208 #endif