PLearn 0.1
PTimer.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines