00001 /* 00002 * perf.h 00003 * 00004 * Copyright (C) 2006,2007,2010 Thomas A. Vaughan 00005 * All rights reserved. 00006 * 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * * Neither the name of the <organization> nor the 00016 * names of its contributors may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY 00020 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY 00023 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00026 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * 00031 * Performance timers for (duh) timing. Should be threadsafe! 00032 */ 00033 00034 #ifndef WAVEPACKET_PERF_H__ 00035 #define WAVEPACKET_PERF_H__ 00036 00037 // includes -------------------------------------------------------------------- 00038 #include "common/common.h" 00039 00040 #ifdef WIN32 00041 #include <winsock2.h> 00042 int gettimeofday(OUT struct timeval * tv, OUT struct timezone * tz); 00043 #endif // WIN32 00044 00045 00046 namespace perf { 00047 00048 00049 /// \ingroup general 00050 /*@{*/ 00051 00052 00053 //////////////////////////////////////////////////////////////////////////////// 00054 /// 00055 /// \defgroup perf Performance Timers API 00056 /// 00057 /// A set of simple timers (and time objects) used to quickly generate 00058 /// information about how the code is performing. 00059 /// 00060 //////////////////////////////////////////////////////////////////////////////// 00061 /*@{*/ 00062 00063 /// yes, my own time_t for convenience in the perf library 00064 struct time_t { 00065 // constructor, manipulators 00066 time_t(IN long in_sec, IN long in_usec) throw() { 00067 this->set(in_sec, in_usec); 00068 } 00069 time_t(void) throw() { this->clear(); } 00070 00071 void increment(IN const time_t& t) throw() { 00072 // increment uSeconds, and account for rollover 00073 useconds += t.useconds; 00074 int nSecs = useconds / 1000000; 00075 useconds = useconds % 1000000; 00076 00077 // now increment seconds 00078 seconds += nSecs; 00079 seconds += t.seconds; 00080 } 00081 00082 void decrement(IN const time_t& t) throw() { 00083 00084 // DPRINTF("Have: %ld sec %ld usec", seconds, useconds); 00085 // DPRINTF(" dec %ld sec %ld usec", t.seconds, t.useconds); 00086 00087 // decrement uSeconds, borrow if necessary 00088 if (t.useconds > useconds) { 00089 useconds += 1000000; 00090 --seconds; 00091 } 00092 00093 useconds -= t.useconds; 00094 seconds -= t.seconds; 00095 00096 ASSERT(useconds >= 0 && useconds < 1000000, 00097 "Bad microseconds: %ld", useconds); 00098 if (seconds < 0) { 00099 DPRINTF("Negative seconds!"); 00100 DPRINTF("Input: seconds=%ld useconds=%ld", 00101 t.seconds, t.useconds); 00102 DPRINTF("Local: seconds=%ld useconds=%ld", 00103 seconds, useconds); 00104 // ASSERT(false, "Input > Local?"); 00105 00106 // this happens when someone resets the system 00107 // clock while we're timing. Just use zero 00108 seconds = 0; 00109 useconds = 0; 00110 } 00111 // DPRINTF(" now %ld sec %ld usec", seconds, useconds); 00112 } 00113 00114 bool isGreaterThan(IN const time_t& t) const throw() { 00115 if (seconds > t.seconds) 00116 return true; 00117 if (seconds < t.seconds) 00118 return false; 00119 return (useconds > t.useconds); 00120 } 00121 00122 double getSeconds(void) const throw() { 00123 return (1.0 * seconds) + (1.0e-6 * useconds); 00124 } 00125 00126 long getMicroseconds(void) const throw() { 00127 return useconds; 00128 } 00129 00130 void clear(void) throw() { 00131 seconds = useconds = 0; 00132 } 00133 00134 void set(IN long in_sec, IN long in_usec) throw() { 00135 ASSERT(in_sec >= 0, "Invalid seconds: %ld", in_sec); 00136 ASSERT(in_usec >= 0 && in_usec < 1000000, 00137 "Invalid microseconds: %ld", in_usec); 00138 00139 seconds = in_sec; 00140 useconds = in_usec; 00141 } 00142 00143 private: 00144 // data fields 00145 long seconds; 00146 long useconds; 00147 }; 00148 00149 00150 00151 //////////////////////////////////////////////////////////////////////////////// 00152 /// 00153 /// Timer class -- just throw one of these on the stack with a unique name 00154 /// 00155 /// When the timer destructs, it will register the time. At the end of 00156 /// program execution (actually, at any time!) you can call 00157 /// getTimingSummary() and retrieve the list of all timers encountered and 00158 /// basic statistics. 00159 /// 00160 /// Example: 00161 /// \code 00162 /// void myFunction(void) { 00163 /// perf::Timer timer("myFunction"); 00164 /// dosomething(); 00165 /// dosomething_else(); 00166 /// { 00167 /// perf::Timer timer("myFunction--expensive"); 00168 /// dosomething_expensive(); 00169 // } 00170 /// } 00171 /// \endcode 00172 //////////////////////////////////////////////////////////////////////////////// 00173 00174 class Timer { 00175 public: 00176 Timer(const char * name); 00177 ~Timer(void); 00178 00179 private: 00180 // disallowed operations 00181 Timer(const Timer&); 00182 const Timer& operator = (const Timer&); 00183 00184 // private data 00185 time_t m_start_time; 00186 void *m_context; 00187 }; 00188 00189 00190 00191 //////////////////////////////////////////////////////////////////////////////// 00192 // 00193 // DebugTimer -- prints to stderr on destruction 00194 // 00195 //////////////////////////////////////////////////////////////////////////////// 00196 00197 class DebugTimer { 00198 public: 00199 DebugTimer(IN const char * msg); 00200 ~DebugTimer(void) throw(); 00201 00202 private: 00203 DebugTimer(const DebugTimer&); 00204 const DebugTimer& operator = (const DebugTimer&); 00205 00206 // data 00207 time_t m_start_time; 00208 std::string m_msg; 00209 }; 00210 00211 00212 00213 //////////////////////////////////////////////////////////////////////////////// 00214 // 00215 // Other public APIs (reporting mostly) 00216 // 00217 //////////////////////////////////////////////////////////////////////////////// 00218 00219 /// return time_t object containing current time 00220 time_t getNow(void) throw(); 00221 00222 /// you can disable the timing system 00223 /// it is better to remove verbose timers, however! 00224 /// 00225 /// TODO: remove this function altogether? 00226 void enableTimers(IN bool enabled) throw(); // enabled by default 00227 00228 00229 /// return a string containing (human-readable) formatted timing information 00230 void getTimingSummary(OUT std::string&); 00231 00232 /// dumps timing summary to the given stream 00233 void dumpTimingSummary(IO std::ostream&); 00234 00235 }; // perf namespace 00236 00237 00238 /*@}*/ // end documentation block 00239 00240 00241 #endif // WAVEPACKET_PERF_H__ 00242