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