PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PTimer.cc 00004 // 00005 // Copyright (C) 2006 Olivier Delalleau 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 // Authors: Olivier Delalleau 00036 00040 #include "PTimer.h" 00041 00042 namespace PLearn { 00043 using namespace std; 00044 00045 PLEARN_IMPLEMENT_OBJECT( 00046 PTimer, 00047 "Allows measurement of time elapsed between two events.", 00048 "A single PTimer object can contain many timers, each being identified\n" 00049 "by a unique name.\n" 00050 "The time is measured in seconds. For short durations (less than 30\n" 00051 "minutes), it is measured precisely, while for longer durations it is\n" 00052 "approximated to an integer number.\n" 00053 "\n" 00054 "Note that for advanced profiling, one should probably use the\n" 00055 "Profiler class instead.\n" 00056 "For short duration or when the option use_time_fct is false we will use\n" 00057 "the clock() function that takes the sum of all child threads. Otherwise\n" 00058 "we use the time(0) function that reports the wall time.\n" 00059 ); 00060 00062 // PTimer // 00064 PTimer::PTimer() 00065 :use_time_fct(false) 00066 {} 00067 00068 PTimer::PTimer(bool use_time_fct_, bool call_build_): 00069 inherited(call_build_), 00070 use_time_fct(use_time_fct_) 00071 { 00072 if (call_build_) 00073 build_(); 00074 } 00075 00077 // build // 00079 void PTimer::build() 00080 { 00081 inherited::build(); 00082 build_(); 00083 } 00084 00086 // makeDeepCopyFromShallowCopy // 00088 void PTimer::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00089 { 00090 inherited::makeDeepCopyFromShallowCopy(copies); 00091 deepCopyField(start_clock_t, copies); 00092 deepCopyField(start_long, copies); 00093 deepCopyField(total_times, copies); 00094 } 00095 00097 // declareOptions // 00099 void PTimer::declareOptions(OptionList& ol) 00100 { 00101 // ### Declare all of this object's options here 00102 // ### For the "flags" of each option, you should typically specify 00103 // ### one of OptionBase::buildoption, OptionBase::learntoption or 00104 // ### OptionBase::tuningoption. Another possible flag to be combined with 00105 // ### is OptionBase::nosave 00106 00107 declareOption(ol, "name_to_idx", &PTimer::name_to_idx, 00108 OptionBase::learntoption, 00109 "Map a timer's name to its internal integer index."); 00110 00111 declareOption(ol, "total_times", &PTimer::total_times, 00112 OptionBase::learntoption, 00113 "Contains the current total times of all timers."); 00114 00115 declareOption(ol, "use_time_fct", &PTimer::use_time_fct, 00116 OptionBase::buildoption, 00117 "If true, we will use the time(0) function. So we will report the\n" 00118 "wall time. Useful in multithread case."); 00119 00120 // Now call the parent class' declareOptions 00121 inherited::declareOptions(ol); 00122 } 00123 00125 // build_ // 00127 void PTimer::build_() 00128 { 00129 // ### This method should do the real building of the object, 00130 // ### according to set 'options', in *any* situation. 00131 // ### Typical situations include: 00132 // ### - Initial building of an object from a few user-specified options 00133 // ### - Building of a "reloaded" object: i.e. from the complete set of all serialised options. 00134 // ### - Updating or "re-building" of an object after a few "tuning" options have been modified. 00135 // ### You should assume that the parent class' build_() has already been called. 00136 int n_timers = total_times.length(); 00137 start_long.resize(n_timers); 00138 start_clock_t.resize(n_timers); 00139 } 00140 00142 // getTimer // 00144 real PTimer::getTimer(const string& timer_name) 00145 { 00146 PLASSERT( name_to_idx.find(timer_name) != name_to_idx.end() ); 00147 int timer_id = name_to_idx[timer_name]; 00148 return total_times[timer_id]; 00149 } 00150 00152 // newTimer // 00154 void PTimer::newTimer(const string& timer_name, bool can_exist) 00155 { 00156 if(!can_exist) 00157 PLASSERT( name_to_idx.find(timer_name) == name_to_idx.end() ); 00158 int n_timers = total_times.length(); 00159 name_to_idx[timer_name] = n_timers; 00160 total_times.append(0); 00161 build(); 00162 } 00163 00165 // resetAllTimers // 00167 void PTimer::resetAllTimers() 00168 { 00169 map<string, int>::const_iterator it; 00170 for (it = name_to_idx.begin(); it != name_to_idx.end(); it++) 00171 resetTimer(it->first); 00172 } 00173 00175 // resetTimer // 00177 void PTimer::resetTimer(const string& timer_name) 00178 { 00179 PLASSERT( name_to_idx.find(timer_name) != name_to_idx.end() ); 00180 int timer_id = name_to_idx[timer_name]; 00181 total_times[timer_id] = 0; 00182 } 00183 00185 // startTimer // 00187 void PTimer::startTimer(const string& timer_name) 00188 { 00189 map<string, int>::const_iterator it = name_to_idx.find(timer_name); 00190 if (it == name_to_idx.end()) { 00191 // The timer does not already exist. 00192 this->newTimer(timer_name); 00193 it = name_to_idx.find(timer_name); 00194 } 00195 int timer_id = it->second; 00196 start_long[timer_id] = long(time(0)); 00197 start_clock_t[timer_id] = clock(); 00198 } 00199 00201 // stopTimer // 00203 void PTimer::stopTimer(const string& timer_name) 00204 { 00205 PLASSERT( name_to_idx.find(timer_name) != name_to_idx.end() ); 00206 int timer_id = name_to_idx[timer_name]; 00207 clock_t time_clock_t = clock() - start_clock_t[timer_id]; 00208 long time_long = long(time(0)) - start_long[timer_id]; 00209 if (time_long > 1800 || use_time_fct) 00210 // More than 30 mins: we use the approximate length. 00211 total_times[timer_id] += time_long; 00212 else 00213 // Less than 30 mins: we use the more precise length. 00214 total_times[timer_id] += time_clock_t / real(CLOCKS_PER_SEC); 00215 } 00216 00217 } // end of namespace PLearn 00218 00219 00220 /* 00221 Local Variables: 00222 mode:c++ 00223 c-basic-offset:4 00224 c-file-style:"stroustrup" 00225 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00226 indent-tabs-mode:nil 00227 fill-column:79 00228 End: 00229 */ 00230 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :