1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTimerLog.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkTimerLog
17  * @brief   Timer support and logging
18  *
19  * vtkTimerLog contains walltime and cputime measurements associated
20  * with a given event.  These results can be later analyzed when
21  * "dumping out" the table.
22  *
23  * In addition, vtkTimerLog allows the user to simply get the current
24  * time, and to start/stop a simple timer separate from the timing
25  * table logging.
26 */
27 
28 #ifndef vtkTimerLog_h
29 #define vtkTimerLog_h
30 
31 #include "vtkCommonSystemModule.h" // For export macro
32 #include "vtkObject.h"
33 
34 #include <string> // STL Header
35 #include <vector> // STL Header
36 
37 #ifdef _WIN32
38 #include <sys/types.h> // Needed for Win32 implementation of timer
39 #include <sys/timeb.h> // Needed for Win32 implementation of timer
40 #else
41 #include <time.h>      // Needed for unix implementation of timer
42 #include <sys/time.h>  // Needed for unix implementation of timer
43 #include <sys/types.h> // Needed for unix implementation of timer
44 #include <sys/times.h> // Needed for unix implementation of timer
45 #endif
46 
47 // var args
48 #ifndef _WIN32
49 #include <unistd.h>    // Needed for unix implementation of timer
50 #endif
51 
52 // select stuff here is for sleep method
53 #ifndef NO_FD_SET
54 #   define SELECT_MASK fd_set
55 #else
56 #   ifndef _AIX
57         typedef long fd_mask;
58 #   endif
59 #   if defined(_IBMR2)
60 #       define SELECT_MASK void
61 #   else
62 #       define SELECT_MASK int
63 #   endif
64 #endif
65 
66 struct vtkTimerLogEntry
67 {
68   enum LogEntryType
69   {
70     INVALID = -1,
71     STANDALONE,    // an individual, marked event
72     START,         // start of a timed event
73     END,           // end of a timed event
74     INSERTED       // externally timed value
75   };
76   double WallTime;
77   int CpuTicks;
78   std::string Event;
79   LogEntryType Type;
80   unsigned char Indent;
vtkTimerLogEntryvtkTimerLogEntry81   vtkTimerLogEntry() : WallTime(0), CpuTicks(0), Type(INVALID), Indent(0)
82     {}
83 };
84 
85 class VTKCOMMONSYSTEM_EXPORT vtkTimerLog : public vtkObject
86 {
87 public:
88   static vtkTimerLog *New();
89 
90   vtkTypeMacro(vtkTimerLog,vtkObject);
91   void PrintSelf(ostream& os, vtkIndent indent) override;
92 
93   /**
94    * This flag will turn logging of events off or on.
95    * By default, logging is on.
96    */
SetLogging(int v)97   static void SetLogging(int v) {vtkTimerLog::Logging = v;}
GetLogging()98   static int GetLogging() {return vtkTimerLog::Logging;}
LoggingOn()99   static void LoggingOn() {vtkTimerLog::SetLogging(1);}
LoggingOff()100   static void LoggingOff() {vtkTimerLog::SetLogging(0);}
101 
102   //@{
103   /**
104    * Set/Get the maximum number of entries allowed in the timer log
105    */
106   static void SetMaxEntries(int a);
107   static int  GetMaxEntries();
108   //@}
109 
110   /**
111    * Record a timing event.  The event is represented by a formatted
112    * string.
113    */
114   static void FormatAndMarkEvent(const char *EventString, ...);
115 
116   //@{
117   /**
118    * Write the timing table out to a file.  Calculate some helpful
119    * statistics (deltas and percentages) in the process.
120    */
121   static void DumpLog(const char *filename);
122   //@}
123 
124   //@{
125   /**
126    * I want to time events, so I am creating this interface to
127    * mark events that have a start and an end.  These events can be,
128    * nested. The standard Dumplog ignores the indents.
129    */
130   static void MarkStartEvent(const char *EventString);
131   static void MarkEndEvent(const char *EventString);
132   //@}
133 
134   //@{
135   /**
136    * Insert an event with a known wall time value (in seconds)
137    * and cpuTicks.
138    */
139   static void InsertTimedEvent(
140     const char *EventString, double time, int cpuTicks);
141   //@}
142 
143   static void DumpLogWithIndents(ostream *os, double threshold);
144   static void DumpLogWithIndentsAndPercentages(ostream *os);
145 
146   //@{
147   /**
148    * Programmatic access to events.  Indexed from 0 to num-1.
149    */
150   static int GetNumberOfEvents();
151   static int GetEventIndent(int i);
152   static double GetEventWallTime(int i);
153   static const char* GetEventString(int i);
154   static vtkTimerLogEntry::LogEntryType GetEventType(int i);
155   //@}
156 
157   /**
158    * Record a timing event and capture wall time and cpu ticks.
159    */
160   static void MarkEvent(const char *EventString);
161 
162   /**
163    * Clear the timing table.  walltime and cputime will also be set
164    * to zero when the first new event is recorded.
165    */
166   static void ResetLog();
167 
168   //@{
169   /**
170    * Allocate timing table with MaxEntries elements.  @deprecated
171    * AllocateLog() should be replaced with SetMaxEntries() (VTK 7.1.0).
172    */
173   static void AllocateLog();
174   //@}
175 
176   /**
177    * Remove timer log.
178    */
179   static void CleanupLog();
180 
181   /**
182    * Returns the elapsed number of seconds since January 1, 1970. This
183    * is also called Universal Coordinated Time.
184    */
185   static double GetUniversalTime();
186 
187   /**
188    * Returns the CPU time for this process
189    * On Win32 platforms this actually returns wall time.
190    */
191   static double GetCPUTime();
192 
193   /**
194    * Set the StartTime to the current time. Used with GetElapsedTime().
195    */
196   void StartTimer();
197 
198   /**
199    * Sets EndTime to the current time. Used with GetElapsedTime().
200    */
201   void StopTimer();
202 
203   /**
204    * Returns the difference between StartTime and EndTime as
205    * a doubleing point value indicating the elapsed time in seconds.
206    */
207   double GetElapsedTime();
208 
209 protected:
vtkTimerLog()210   vtkTimerLog() {this->StartTime=0; this->EndTime = 0;}; //insure constructor/destructor protected
~vtkTimerLog()211   ~vtkTimerLog() override { };
212 
213   static int               Logging;
214   static int               Indent;
215   static int               MaxEntries;
216   static int               NextEntry;
217   static int               WrapFlag;
218   static int               TicksPerSecond;
219   static std::vector<vtkTimerLogEntry> TimerLog;
220 
221 #ifdef _WIN32
222 #ifndef _WIN32_WCE
223   static timeb             FirstWallTime;
224   static timeb             CurrentWallTime;
225 #else
226   static FILETIME FirstWallTime;
227   static FILETIME CurrentWallTime;
228 #endif
229 #else
230   static timeval           FirstWallTime;
231   static timeval           CurrentWallTime;
232   static tms               FirstCpuTicks;
233   static tms               CurrentCpuTicks;
234 #endif
235 
236   /**
237    * Record a timing event and capture wall time and cpu ticks.
238    */
239   static void MarkEventInternal(
240     const char *EventString, vtkTimerLogEntry::LogEntryType type,
241     vtkTimerLogEntry* entry = nullptr);
242 
243   // instance variables to support simple timing functionality,
244   // separate from timer table logging.
245   double StartTime;
246   double EndTime;
247 
248   static vtkTimerLogEntry* GetEvent(int i);
249 
250   static void DumpEntry(ostream& os, int index, double time, double deltatime,
251                         int tick, int deltatick, const char *event);
252 
253 private:
254   vtkTimerLog(const vtkTimerLog&) = delete;
255   void operator=(const vtkTimerLog&) = delete;
256 };
257 
258 /**
259  * Helper class to log time within scope
260  */
261 class vtkTimerLogScope
262 {
263 public:
vtkTimerLogScope(const char * eventString)264   vtkTimerLogScope(const char* eventString)
265   {
266     if (eventString)
267     {
268       this->EventString = eventString;
269     }
270     vtkTimerLog::MarkStartEvent(eventString);
271   }
272 
~vtkTimerLogScope()273   ~vtkTimerLogScope()
274   {
275     vtkTimerLog::MarkEndEvent(this->EventString.c_str());
276   };
277 
278 protected:
279   std::string EventString;
280 private:
281   vtkTimerLogScope(const vtkTimerLogScope&) = delete;
282   void operator=(const vtkTimerLogScope&) = delete;
283 };
284 
285 //
286 // Set built-in type.  Creates member Set"name"() (e.g., SetVisibility());
287 //
288 #define vtkTimerLogMacro(string) \
289   { \
290       vtkTimerLog::FormatAndMarkEvent("Mark: In %s, line %d, class %s: %s", \
291                               __FILE__, __LINE__, this->GetClassName(), string); \
292   }
293 
294 #endif
295