1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: lyt_Stopwatch.h 4 5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain proprietary 8 information of Nintendo and/or its licensed developers and are protected by 9 national and international copyright laws. They may not be disclosed to third 10 parties or copied or duplicated in any form, in whole or in part, without the 11 prior written consent of Nintendo. 12 13 The content herein is highly confidential and should be handled accordingly. 14 15 $Revision: 31311 $ 16 *---------------------------------------------------------------------------*/ 17 18 #ifndef NW_LYT_STOPWATCH_H_ 19 #define NW_LYT_STOPWATCH_H_ 20 21 #include <climits> 22 #include <math.h> 23 #include <nw/sdk.h> 24 #include <nw/ut/ut_LinkList.h> 25 26 #ifdef NW_PLATFORM_CTR 27 #include <nn/os/os_Tick.h> 28 #endif 29 30 namespace nw { 31 namespace lyt { 32 namespace internal { 33 34 #define NW_LYT_PROFILE 1 35 36 #ifdef NW_LYT_PROFILE 37 # define NW_LYT_JOIN(x, y) NW_LYT_JOIN_AGAIN(x, y) 38 # define NW_LYT_JOIN_AGAIN(x, y) x ## y 39 40 # define NW_LYT_STOPWATCH_MEASURE(no, label) \ 41 nw::lyt::internal::Measure NW_LYT_JOIN(measure, __LINE__) ( \ 42 nw::lyt::internal::Stopwatch::Instance<no>(label), no) 43 44 # define NW_LYT_STOPWATCH_START(no, label) \ 45 if(nw::lyt::internal::Stopwatch::IsTarget(no)) \ 46 nw::lyt::internal::Stopwatch::Instance<no>().Start(label) 47 48 # define NW_LYT_STOPWATCH_STOP(no) \ 49 if(nw::lyt::internal::Stopwatch::IsTarget(no)) \ 50 nw::lyt::internal::Stopwatch::Instance<no>().Stop() 51 #else 52 # define NW_LYT_STOPWATCH_MEASURE(no, label) 53 # define NW_LYT_STOPWATCH_START(no, label) 54 # define NW_LYT_STOPWATCH_STOP(no) 55 #endif 56 57 #ifdef NW_PLATFORM_CTR 58 using nn::fnd::TimeSpan; 59 using nn::os::Tick; 60 #endif 61 62 //--------------------------------------------------------------------------- 63 //! 経過時間を計測します。 64 //--------------------------------------------------------------------------- 65 class Stopwatch : public nw::ut::LinkListNode 66 { 67 public: 68 static const s64 S64_MAX = (s64)(((u64)-1) >> 1); 69 70 //! インスタンスを保持するリストです。 71 typedef nw::ut::LinkList<Stopwatch, 0> List; 72 73 //! @brief コンストラクタです。 74 Stopwatch(int no = 0, const char* label = NULL); 75 76 //! @brief 計測を開始します。 77 //! 78 //! @param label 計測対象を示すラベルを指定できます。 79 //! 80 void Start(const char* label = NULL) 81 { 82 #ifndef NW_PLATFORM_CTR 83 NW_UNUSED_VARIABLE(label) 84 #else 85 if (label != NULL) 86 { 87 this->SetLabel(label); 88 } 89 90 NW_ASSERT(!this->IsRunning()); 91 92 m_StartTick = Tick::GetSystemCurrent(); 93 #endif 94 } 95 96 //! @brief 計測を停止します。 Stop()97 void Stop() 98 { 99 #ifdef NW_PLATFORM_CTR 100 Tick stopTick = Tick::GetSystemCurrent(); 101 102 NW_ASSERT(this->IsRunning()); 103 104 Tick elapsed = stopTick - m_StartTick; 105 m_StartTick = Tick(); 106 107 if (s64(elapsed) < m_MinSample) 108 { 109 m_MinSample = s64(elapsed); 110 } 111 112 if (s64(elapsed) > m_MaxSample) 113 { 114 m_MaxSample = s64(elapsed); 115 } 116 117 m_TotalTick += elapsed; 118 ++m_Count; 119 #endif 120 } 121 122 void Reset(); 123 124 static void ResetAll(); 125 126 //! @brief 番号を設定します。 SetNo(int no)127 void SetNo(int no) 128 { 129 #ifndef NW_PLATFORM_CTR 130 NW_UNUSED_VARIABLE(no); 131 #else 132 m_No = no; 133 #endif 134 } 135 136 //! @brief ラベルを設定します。 SetLabel(const char * label)137 void SetLabel(const char* label) 138 { 139 #ifndef NW_PLATFORM_CTR 140 NW_UNUSED_VARIABLE(label); 141 #else 142 m_Label = label; 143 #endif 144 } 145 146 #ifdef NW_PLATFORM_CTR 147 //! @brief 計測中か調べます。 IsRunning()148 bool IsRunning() const 149 { 150 return m_StartTick != Tick(); 151 } 152 153 //! @brief 番号を取得します。 GetNo()154 int GetNo() const 155 { 156 return m_No; 157 } 158 159 //! @brief ラベルを取得します。 GetLabel()160 const char* GetLabel() const 161 { 162 return m_Label; 163 } 164 165 //! @brief 経過時間の合計を取得します。 GetElapsedTime()166 const TimeSpan GetElapsedTime() const 167 { 168 return m_TotalTick; 169 } 170 171 //! @brief 測定回数を取得します。 GetCount()172 int GetCount() const 173 { 174 return m_Count; 175 } 176 177 //! @brief 最小値のサンプルを取得します。 GetMinSample()178 TimeSpan GetMinSample() const 179 { 180 if (m_Count == 0) 181 { 182 return Tick(0).ToTimeSpan(); 183 } 184 else 185 { 186 return Tick(m_MinSample).ToTimeSpan(); 187 } 188 } 189 190 //! @brief 最大値のサンプルを取得します。 GetMaxSample()191 TimeSpan GetMaxSample() const 192 { 193 if (m_Count == 0) 194 { 195 return Tick(0).ToTimeSpan(); 196 } 197 else 198 { 199 return Tick(m_MaxSample).ToTimeSpan(); 200 } 201 } 202 #endif 203 204 //! @brief インスタンスを取得します。 205 //! 206 //! @tparam no 計測対象に固有の番号を指定します。 207 //! @param label 計測対象を示すラベルが指定できます。 208 //! 209 template <int no> 210 static Stopwatch& Instance(const char* label = NULL) 211 { 212 static Stopwatch obj(no); 213 214 if (label != NULL) 215 { 216 obj.SetLabel(label); 217 } 218 219 return obj; 220 } 221 222 //! @brief インスタンスのリストを取得します。 GetList()223 static List& GetList() 224 { 225 static List list; 226 return list; 227 } 228 229 //! @brief 計測を有効にします。 230 //! @details 231 //! SetTargetNo() で全インスタンス番号を指定するのと等価です。 232 static void Enable(); 233 234 //! @brief 計測を無効にします。 235 //! @details 236 //! SetTargetNo() で min > max を指定するのと等価です。 237 static void Disable(); 238 239 //! @brief インスタンス番号が計測対象かどうかを判定します。 IsTarget(int no)240 static bool IsTarget(int no) 241 { 242 return s_TargetNoMin <= no && no <= s_TargetNoMax; 243 } 244 245 //! @brief 計測対象とするインスタンス番号の範囲を設定します。 SetTargetNo(int min,int max)246 static void SetTargetNo(int min, int max) 247 { 248 s_TargetNoMin = min; 249 s_TargetNoMax = max; 250 } 251 252 //! @brief 計測対象とするインスタンス番号を設定します。 SetTargetNo(int no)253 static void SetTargetNo(int no) 254 { 255 SetTargetNo(no, no); 256 } 257 258 //! @brief 計測結果をコンソールに出力します。 259 static void Dump(const Stopwatch& stopwatch); 260 261 //! @brief すべての計測結果をコンソールに出力します。 262 static void Dump(); 263 264 //! @brief 計測結果のヘッダを出力します。 265 static void DumpHeader(); 266 267 protected: 268 #ifdef NW_PLATFORM_CTR 269 //! @details :private 270 int m_Count; 271 272 //! @details :private 273 int m_No; 274 275 //! @details :private 276 const char* m_Label; 277 278 //! @details :private 279 Tick m_TotalTick; 280 281 //! @details :private 282 Tick m_StartTick; 283 284 //! @details :private 285 s64 m_MinSample; 286 287 //! @details :private 288 s64 m_MaxSample; 289 #endif 290 291 //! @details :private 292 static int s_TargetNoMin; 293 294 //! @details :private 295 static int s_TargetNoMax; 296 }; 297 298 //--------------------------------------------------------------------------- 299 //! 計測の開始と終了を自動化します。 300 //--------------------------------------------------------------------------- 301 class Measure 302 { 303 public: Measure(Stopwatch & stopwatch,int no)304 Measure(Stopwatch& stopwatch, int no) 305 : m_Stopwatch(stopwatch) 306 { 307 #ifdef NW_PLATFORM_CTR 308 if(Stopwatch::IsTarget(no)) 309 { 310 m_Stopwatch.Start(); 311 } 312 #endif 313 } 314 ~Measure()315 ~Measure() 316 { 317 #ifdef NW_PLATFORM_CTR 318 if(m_Stopwatch.IsRunning()) 319 { 320 m_Stopwatch.Stop(); 321 } 322 #endif 323 } 324 325 protected: 326 //! @details :private 327 Stopwatch& m_Stopwatch; 328 }; 329 330 } // namespace internal 331 } // namespace lyt 332 } // namespace nw 333 334 #endif // NW_LYT_STOPWATCH_H_ 335