HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
COP2_DebugTiming.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: COP2_DebugTiming.h
7  *
8  * COMMENTS:
9  * This class allows for timing of specific nodes within a series of
10  * cooks.
11  */
12 #ifndef COP2_DebugTiming_H
13 #define COP2_DebugTiming_H
14 
15 #include <iostream>
16 #include <UT/UT_Lock.h>
17 #include <UT/UT_String.h>
18 #include <UT/UT_SymbolTable.h>
19 #include <UT/UT_StopWatch.h>
21 #include <SYS/SYS_Math.h>
22 #include <OP/OP_Node.h>
23 
24 #include "COP2_API.h"
25 
27 
29 {
30 public:
31  COP2_DebugTimingNode(const char *nodepath)
32  : myNodePath(nodepath, 1),
33  myNumCooks(0),
34  myTotalCookTime(0.0),
35  myMinCookTime(0.0),
36  myMaxCookTime(0.0)
37  { }
38 
39  void addCookTime(double time)
40  {
41  if(myNumCooks == 0)
42  {
43  myMinCookTime = time;
44  myMaxCookTime = time;
45  }
46  else
47  {
48  myMinCookTime = SYSmin(time, myMinCookTime);
49  myMaxCookTime = SYSmax(time, myMaxCookTime);
50  }
51  myTotalCookTime += time;
52  myNumCooks++;
53  }
54 
55  void print(std::ostream &os) const
56  {
57  if(myNumCooks > 0.0)
58  os << myNodePath << "\n " << myNumCooks << " "
59  << myTotalCookTime <<"s min " << myMinCookTime << "s max "
60  << myMaxCookTime << "s avg "
61  << (myTotalCookTime / myNumCooks) << "s";
62  else
63  os << myNodePath << " not cooked.";
64  }
65 
69  double myMinCookTime;
70  double myMaxCookTime;
71 };
72 
74 {
75  std::ostream *os;
76  double total_time;
77 };
78 
79 
80 inline int printEntry(COP2_DebugTimingNode *&node, const char *, void *vdata)
81 {
83 
84  node->print(*pdata->os);
85  *pdata->os << "\n";
86  pdata->total_time += node->myTotalCookTime;
87  return 1;
88 }
89 
90 inline int clearEntry(COP2_DebugTimingNode *&node, const char *, void *)
91 {
92  delete node;
93  return 1;
94 }
95 
96 
98 {
99 public:
100  COP2_DebugTimingTable() : myTotal(0.0) {}
102  {
103  myTable.traverse(clearEntry, NULL);
104  }
105 
106  void addCopTiming(OP_Node *copnode, double time)
107  {
108  UT_String path;
109  COP2_DebugTimingNode *tnode = NULL;
110 
111  copnode->getFullPath(path);
112 
113  myTableLock.lock();
114 
115  if(!myTable.findSymbol(path, &tnode))
116  {
117  tnode = new COP2_DebugTimingNode(path);
118  myTable.addSymbol(path, tnode);
119  }
120 
121  tnode->addCookTime(time);
122 
123  myTableLock.unlock();
124  }
125 
126  void printTable(std::ostream &os)
127  {
129  pdata.os = &os;
130  pdata.total_time = 0.0;
131  myTable.traverse(printEntry, &pdata);
132  os.flush();
133  os << "Total time: " << pdata.total_time << "s\n";
134  os.flush();
135  }
136 
139  double myTotal;
140 };
141 
142 
144 {
145  void start(const char *name)
146  {
147  myWatches[name].resume();
148  }
149 
150  void stop(const char *name)
151  {
152  // Don't create a stopwatch if none exists.
153  if (myWatches.contains(name))
154  myWatches[name].stop();
155  }
156 
158 };
159 
161 {
163 public:
164  cop2_Watches &get() { return myWatches.get(); }
165 
166  void printTimes(const char *indent = "")
167  {
169 
170  using std::cerr;
171  for (ThreadWatches::const_iterator it = myWatches.begin();
172  it != myWatches.end(); ++it)
173  {
174  const cop2_Watches &wl = it.get();
175 
176  if (wl.myWatches.empty())
177  continue;
178 
179  cerr << indent << "Thread " << it.thread() << ":\n";
180 
181  for (auto itW = wl.myWatches.begin(); !itW.atEnd(); ++itW)
182  {
183  cerr << indent << " " << itW.name() << " : " << itW.thing().getTime() << "s\n";
184  if (!sum.contains(itW.name()))
185  sum[itW.name()] = itW.thing().getTime();
186  else
187  sum[itW.name()] += itW.thing().getTime();
188  }
189  }
190 
191  cerr << indent << "Thread Total:\n";
192  for (auto itW = sum.begin(); !itW.atEnd(); ++itW)
193  {
194  cerr << indent << " " << itW.name() << " : " << itW.thing() << "s\n";
195  }
196  }
197 
198  void clear()
199  {
200  for (ThreadWatches::iterator it = myWatches.begin();
201  it != myWatches.end(); ++it)
202  {
203  it.get().myWatches.clear();
204  }
205  }
206 
207 private:
208  ThreadWatches myWatches;
209 };
210 
212 {
213 public:
215  myWatches(w), myName(name)
216  {
217  myWatches.get().start(myName);
218  }
219 
221  {
222  myWatches.get().stop(myName);
223  }
224 
225 private:
226  cop2_ThreadWatches &myWatches;
227  const char *myName;
228 };
229 
230 #endif
void addCopTiming(OP_Node *copnode, double time)
#define SYSmax(a, b)
Definition: SYS_Math.h:1367
void start(const char *name)
std::ostream * os
UT_SymbolMap< UT_StopWatch > myWatches
void stop(const char *name)
GT_API const UT_StringHolder time
GLsizei const GLchar *const * path
Definition: glcorearb.h:3340
double total_time
void print(std::ostream &os) const
const char * getFullPath(UT_String &str) const
Definition: PRM_ParmOwner.h:48
cop2_Watches & get()
const_iterator end() const
end() const iterator
void printTimes(const char *indent="")
iterator begin()
void addCookTime(double time)
GLuint const GLchar * name
Definition: glcorearb.h:785
bool contains(const UT_StringRef &symbol) const
Check if a symbol exists.
void printTable(std::ostream &os)
bool empty() const
Check if the map is empty.
UT_SymbolMap< COP2_DebugTimingNode * > myTable
#define COP2_API
Definition: COP2_API.h:10
cop2_ScopedWatch(cop2_ThreadWatches &w, const char *name)
int printEntry(COP2_DebugTimingNode *&node, const char *, void *vdata)
COP2_DebugTimingNode(const char *nodepath)
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
int clearEntry(COP2_DebugTimingNode *&node, const char *, void *)
#define SYSmin(a, b)
Definition: SYS_Math.h:1368
const_iterator begin() const
begin() const iterator