perf.h

Go to the documentation of this file.
00001 /*
00002  * perf.h
00003  *
00004  * Copyright (C) 2006,2007  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 
00041 namespace perf {
00042 
00043 
00044 /// \ingroup general
00045 /*@{*/
00046 
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 ///
00050 /// \defgroup perf Performance Timers API
00051 ///
00052 /// A set of simple timers (and time objects) used to quickly generate
00053 /// information about how the code is performing.
00054 ///
00055 ////////////////////////////////////////////////////////////////////////////////
00056 /*@{*/
00057 
00058 /// yes, my own time_t for convenience in the perf library
00059 struct time_t {
00060         // constructor, manipulators
00061         time_t(IN long in_sec, IN long in_usec) throw() {
00062                         this->set(in_sec, in_usec);
00063                 }
00064         time_t(void) throw() { this->clear(); }
00065 
00066         void increment(IN const time_t& t) throw() {
00067                         // increment uSeconds, and account for rollover
00068                         useconds += t.useconds;
00069                         int nSecs = useconds / 1000000;
00070                         useconds = useconds % 1000000;
00071 
00072                         // now increment seconds
00073                         seconds += nSecs;
00074                         seconds += t.seconds;
00075                 }
00076 
00077         void decrement(IN const time_t& t) throw() {
00078 
00079                         // DPRINTF("Have: %ld sec  %ld usec", seconds, useconds);
00080                         // DPRINTF("  dec %ld sec  %ld usec", t.seconds, t.useconds);
00081 
00082                         // decrement uSeconds, borrow if necessary
00083                         if (t.useconds > useconds) {
00084                                 useconds += 1000000;
00085                                 --seconds;
00086                         }
00087 
00088                         useconds -= t.useconds;
00089                         seconds -= t.seconds;
00090 
00091                         ASSERT(useconds >= 0 && useconds < 1000000,
00092                             "Bad microseconds: %ld", useconds);
00093                         if (seconds < 0) {
00094                                 DPRINTF("Negative seconds!");
00095                                 DPRINTF("Input: seconds=%ld  useconds=%ld",
00096                                     t.seconds, t.useconds);
00097                                 DPRINTF("Local: seconds=%ld  useconds=%ld",
00098                                     seconds, useconds);
00099                                 // ASSERT(false, "Input > Local?");
00100 
00101                                 // this happens when someone resets the system
00102                                 //   clock while we're timing.  Just use zero
00103                                 seconds = 0;
00104                                 useconds = 0;
00105                         }
00106                         // DPRINTF("  now %ld sec  %ld usec", seconds, useconds);
00107                 }
00108 
00109         bool isGreaterThan(IN const time_t& t) const throw() {
00110                         if (seconds > t.seconds)
00111                                 return true;
00112                         if (seconds < t.seconds)
00113                                 return false;
00114                         return (useconds > t.useconds);
00115                 }
00116 
00117         double getSeconds(void) const throw() {
00118                         return (1.0 * seconds) + (1.0e-6 * useconds);
00119                 }
00120 
00121         long getMicroseconds(void) const throw() {
00122                         return useconds;
00123                 }
00124 
00125         void clear(void) throw() {
00126                         seconds = useconds = 0;
00127                 }
00128 
00129         void set(IN long in_sec, IN long in_usec) throw() {
00130                         ASSERT(in_sec >= 0, "Invalid seconds: %ld", in_sec);
00131                         ASSERT(in_usec >= 0 && in_usec < 1000000,
00132                             "Invalid microseconds: %ld", in_usec);
00133 
00134                         seconds = in_sec;
00135                         useconds = in_usec;
00136                 }
00137 
00138 private:
00139         // data fields
00140         long    seconds;
00141         long    useconds;
00142 };
00143 
00144 
00145 
00146 ////////////////////////////////////////////////////////////////////////////////
00147 ///
00148 ///     Timer class -- just throw one of these on the stack with a unique name
00149 ///
00150 ///     When the timer destructs, it will register the time.  At the end of
00151 ///     program execution (actually, at any time!) you can call
00152 ///     getTimingSummary() and retrieve the list of all timers encountered and
00153 ///     basic statistics.
00154 ///
00155 /// Example:
00156 /// \code
00157 ///     void myFunction(void) {
00158 ///             perf::Timer timer("myFunction");
00159 ///             dosomething();
00160 ///             dosomething_else();
00161 ///             {
00162 ///                     perf::Timer timer("myFunction--expensive");
00163 ///                     dosomething_expensive();
00164 //              }
00165 ///     }
00166 /// \endcode
00167 ////////////////////////////////////////////////////////////////////////////////
00168 
00169 class Timer {
00170 public:
00171         Timer(const char * name);
00172         ~Timer(void);
00173 
00174 private:
00175         // disallowed operations
00176         Timer(const Timer&);
00177         const Timer& operator = (const Timer&);
00178 
00179         // private data
00180         time_t          m_start_time;
00181         void           *m_context;
00182 };
00183 
00184 
00185 
00186 ////////////////////////////////////////////////////////////////////////////////
00187 //
00188 //      DebugTimer -- prints to stderr on destruction
00189 //
00190 ////////////////////////////////////////////////////////////////////////////////
00191 
00192 class DebugTimer {
00193 public:
00194         DebugTimer(IN const char * msg);
00195         ~DebugTimer(void) throw();
00196 
00197 private:
00198         DebugTimer(const DebugTimer&);
00199         const DebugTimer& operator = (const DebugTimer&);
00200 
00201         // data
00202         time_t          m_start_time;
00203         std::string     m_msg;
00204 };
00205 
00206 
00207 
00208 ////////////////////////////////////////////////////////////////////////////////
00209 //
00210 //      Other public APIs (reporting mostly)
00211 //
00212 ////////////////////////////////////////////////////////////////////////////////
00213 
00214 /// return time_t object containing current time
00215 time_t getNow(void) throw();
00216 
00217 /// you can disable the timing system
00218 /// it is better to remove verbose timers, however!
00219 ///
00220 /// TODO: remove this function altogether?
00221 void enableTimers(IN bool enabled) throw();     // enabled by default
00222 
00223 
00224 /// return a string containing (human-readable) formatted timing information
00225 void getTimingSummary(OUT std::string&);
00226 
00227 /// dumps timing summary to the given stream
00228 void dumpTimingSummary(IO std::ostream&);
00229 
00230 };      // perf namespace
00231 
00232 
00233 /*@}*/  // end documentation block
00234 
00235 
00236 #endif  // WAVEPACKET_PERF_H__
00237