1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     rdt_Stopwatch.cpp
4 
5   Copyright (C)2009-2012 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: 46347 $
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 // Reset all stopwatch content
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 // Display all stopwatch content
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         // The unit is displayed in microseconds.
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 // Register own instance in the management list.
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 // Delete own instance from the management list.
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