1 /*--------------------------------------------------------------------------
2 Project: Horizon
3 File: rdt_Stopwatch.cpp
4
5 Copyright (C)2010 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 28491 $
14 *-------------------------------------------------------------------------*/
15
16 #include "rdt_Stopwatch.h"
17
18 #include <nn/dbg.h>
19 #include <nn/os.h>
20 #include <nn/fnd.h>
21
22 #include <string.h>
23
24 #ifdef ENABLE_RDT_STOPWATCH
25
26 namespace
27 {
28
29 } // end of anonymous namespace
30
31 namespace nn { namespace rdt { namespace CTR { namespace detail{
32
33
34 bool Stopwatch::s_initialized = false;
35 Stopwatch* Stopwatch::s_paStopwatches[MAX_STOPWATCHES];
36
Initialize(void)37 void Stopwatch::Initialize(void)
38 {
39 if(!s_initialized)
40 {
41 for(int i=0; i<MAX_STOPWATCHES; ++i)
42 {
43 s_paStopwatches[i] = NULL;
44 }
45 s_initialized = true;
46 }
47 else
48 {
49 return; // Do nothing.
50 }
51 }
52
53
Finalize(void)54 void Stopwatch::Finalize(void)
55 {
56 if(s_initialized)
57 {
58 s_initialized = false;
59 }
60 else
61 {
62 NN_LOG("Stopwatch is not initialized, but Finalized() called...\n");
63 // Do nothing.
64 }
65 }
66
67
68 // 全ストップウォッチの内容をリセット
ResetAll(void)69 void Stopwatch::ResetAll(void)
70 {
71 for(int i=0; i<MAX_STOPWATCHES; ++i)
72 {
73 if(s_paStopwatches[i])
74 {
75 s_paStopwatches[i]->Reset();
76 }
77 }
78 }
79
80
81 // 全ストップウォッチの内容を表示
PrintAll(void)82 void Stopwatch::PrintAll(void)
83 {
84 printHeadLine();
85 for(int i=0; i<MAX_STOPWATCHES; ++i)
86 {
87 if(s_paStopwatches[i])
88 {
89 s_paStopwatches[i]->printContents();
90 }
91 }
92 }
93
94
95
Stopwatch(void)96 Stopwatch::Stopwatch(void)
97 {
98 if(!IsInitialized())
99 {
100 NN_LOG("Initialize Stopwatch...\n");
101 Initialize();
102 }
103
104 bool ret = initInstance("(No name)");
105 if(!ret)
106 {
107 NN_LOG("Failed to initInstance().\n");
108 }
109 }
110
111
Stopwatch(const char * name)112 Stopwatch::Stopwatch(const char *name)
113 {
114 NN_NULL_ASSERT(name);
115
116 if(!IsInitialized())
117 {
118 NN_LOG("Initialize Stopwatch...\n");
119 Initialize();
120 }
121
122 bool ret = initInstance(name);
123 if(!ret)
124 {
125 NN_LOG("Failed to initInstance().\n");
126 }
127 }
128
129
~Stopwatch(void)130 Stopwatch::~Stopwatch(void)
131 {
132 removeFromList();
133 }
134
135
Stop(void)136 void Stopwatch::Stop(void)
137 {
138 s64 diff = nn::os::Tick::GetSystemCurrent() - m_start;
139
140 if(diff > m_max)
141 {
142 m_max = diff;
143 }
144
145 if(diff < m_min)
146 {
147 m_min = diff;
148 }
149
150 m_total += diff;
151
152 ++m_times;
153 }
154
155
Print(void) const156 void Stopwatch::Print(void) const
157 {
158 printHeadLine();
159 printContents();
160 }
161
162
printHeadLine(void)163 void Stopwatch::printHeadLine(void)
164 {
165 nn::dbg::detail::Printf( " Average, Min, Max, Total, Times, Name (Unit is usec)\n" );
166 }
167
168
printContents(void) const169 void Stopwatch::printContents(void) const
170 {
171 using nn::dbg::detail::Printf;
172
173 if(m_times > 0)
174 {
175 // 単位はマイクロ秒で表示。
176 s64 total = nnosTickConvertToMicroSeconds(m_total);
177 s64 min = nnosTickConvertToMicroSeconds(m_min);
178 s64 max = nnosTickConvertToMicroSeconds(m_max);
179 f64 avg = static_cast<f64>(total) / m_times;
180 Printf( "%10.2llf, %8lld, %8lld, %10lld, %8d, \"%s\"\n", avg, min, max, total, m_times, m_name);
181 }
182 else if(m_times == 0)
183 {
184 Printf( " ------ NO DATA ------ %s\"\n", m_name);
185 }
186 else
187 {
188 NN_PANIC("m_times is negative! (%d)\n", m_times);
189 }
190 }
191
192
initInstance(const char * name)193 bool Stopwatch::initInstance(const char *name)
194 {
195 Reset();
196 setName(name);
197 return addToList();
198 }
199
200
201 // 管理リストに自分のインスタンスを登録。
addToList(void)202 bool Stopwatch::addToList(void)
203 {
204 for(int i=0; i<MAX_STOPWATCHES; ++i)
205 {
206 if(s_paStopwatches[i]==NULL)
207 {
208 s_paStopwatches[i] = this;
209 return true;
210 }
211 }
212
213 NN_PANIC("No space to addTo(). Too many Stopwatches...");
214 return false;
215 }
216
217
218 // 管理リストから自分のインスタンスを削除。
removeFromList(void)219 void Stopwatch::removeFromList(void)
220 {
221 for(int i=0; i<MAX_STOPWATCHES; ++i)
222 {
223 if(s_paStopwatches[i]==this)
224 {
225 s_paStopwatches[i] = NULL;
226 return;
227 }
228 }
229
230 NN_PANIC("Cannot find my instance! Why?");
231 }
232
233
setName(const char * name)234 void Stopwatch::setName(const char *name)
235 {
236 if(name)
237 {
238 strlcpy(m_name, name, sizeof(m_name));
239 }
240 else
241 {
242 strlcpy(m_name, "(NULL)", sizeof(m_name));
243 }
244 }
245
246
Test(void)247 bool Stopwatch::Test(void)
248 {
249 Stopwatch::Initialize();
250
251 Stopwatch sp("AAABBBCCC");
252
253 for(int i=0; i<100; ++i)
254 {
255 sp.Start();
256 nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(10));
257 sp.Stop();
258 }
259
260 Stopwatch nanashi;
261
262 nanashi.Start();
263 nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMicroSeconds(50));
264 nanashi.Stop();
265
266 Stopwatch::PrintAll();
267
268 Stopwatch::Finalize();
269
270 return true;
271 }
272
273
274
275 }}}} // namespace nn::rdt::CTR::detail
276
277
278 #endif // end of ENABLE_RDT_STOPWATCH
279