CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/FWCore/Services/src/Timing.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Services
00004 // Class  :     Timing
00005 //
00006 // Implementation:
00007 //
00008 // Original Author:  Jim Kowalkowski
00009 //
00010 // Change Log
00011 //
00012 // 1 - mf 4/22/08   Facilitate summary output to job report and logs:
00013 //                  In Timing ctor, default for report_summary_ changed to true
00014 //                  In postEndJob, add output to logger
00015 //
00016 // 2 - 2009/01/14 10:29:00, Natalia Garcia Nebot
00017 //        Modified the service to add some new measurements to report:
00018 //                - Average time per event (cpu and wallclock)
00019 //                - Fastest time per event (cpu and wallclock)
00020 //                - Slowest time per event (cpu and wallclock)
00021 //
00022 // 3 - mf 3/18/09  Change use of LogAbsolute to LogImportant
00023 //                 so that users can throttle the messages
00024 //                 for selected destinations.  LogImportant
00025 //                 is treated at the same level as LogError, so
00026 //                 by default the behavior will not change, but
00027 //                 there will now be a way to control the verbosity.
00028 //
00029 // 4 - mf 3/18/09  The per-event output TimeEvent is changed to LogPrint.
00030 //                 The per-module output TimeModule is changed to LogPrint.
00031 //
00032 // 5 - wmtan 2010/03/16
00033 //                 Fixed the constructor to initialize all data members!
00034 //                 Standardized coding style
00035 //
00036 
00037 #include "FWCore/Services/interface/Timing.h"
00038 #include "FWCore/MessageLogger/interface/JobReport.h"
00039 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
00040 #include "FWCore/ServiceRegistry/interface/Service.h"
00041 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00042 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00043 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00044 #include "FWCore/Utilities/interface/Exception.h"
00045 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00046 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00047 
00048 #include <iostream>
00049 #include <sys/time.h>
00050 #include <sys/resource.h>
00051 #include <sstream>
00052 
00053 namespace edm {
00054   namespace service {
00055 
00056     static std::string d2str(double d) {
00057         std::stringstream t;
00058         t << d;
00059         return t.str();
00060     }
00061 
00062     static double getTime() {
00063       struct timeval t;
00064       if(gettimeofday(&t, 0) < 0)
00065         throw cms::Exception("SysCallFailed", "Failed call to gettimeofday");
00066       return static_cast<double>(t.tv_sec) + (static_cast<double>(t.tv_usec) * 1E-6);
00067     }
00068 
00069     static double getCPU() {
00070         struct rusage usage;
00071         getrusage(RUSAGE_SELF, &usage);
00072 
00073         double totalCPUTime = 0.0;
00074         // User code
00075         totalCPUTime = (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6);
00076         // System functions
00077         totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6);
00078         return totalCPUTime;
00079     }
00080 
00081     Timing::Timing(ParameterSet const& iPS, ActivityRegistry& iRegistry) :
00082         curr_event_(),
00083         curr_job_time_(0.),
00084         curr_job_cpu_(0.),
00085         curr_event_time_(0.),
00086         curr_event_cpu_(0.),
00087         curr_module_time_(0.),
00088         total_event_cpu_(0.),
00089         summary_only_(iPS.getUntrackedParameter<bool>("summaryOnly")),
00090         report_summary_(iPS.getUntrackedParameter<bool>("useJobReport")),
00091         max_event_time_(0.),
00092         max_event_cpu_(0.),
00093         min_event_time_(0.),
00094         min_event_cpu_(0.),
00095         total_event_count_(0) {
00096       iRegistry.watchPostBeginJob(this, &Timing::postBeginJob);
00097       iRegistry.watchPostEndJob(this, &Timing::postEndJob);
00098 
00099       iRegistry.watchPreProcessEvent(this, &Timing::preEventProcessing);
00100       iRegistry.watchPostProcessEvent(this, &Timing::postEventProcessing);
00101 
00102       if (not summary_only_) {
00103         iRegistry.watchPreModule(this, &Timing::preModule);
00104         iRegistry.watchPostModule(this, &Timing::postModule);
00105       }
00106     }
00107 
00108     Timing::~Timing() {
00109     }
00110 
00111     void Timing::fillDescriptions(ConfigurationDescriptions& descriptions) {
00112       ParameterSetDescription desc;
00113       desc.addUntracked<bool>("summaryOnly", false)->setComment(
00114       "If 'true' do not report timing for each event");
00115       desc.addUntracked<bool>("useJobReport", true)->setComment(
00116        "If 'true' write summary information to JobReport");
00117       descriptions.add("Timing", desc);
00118       descriptions.setComment(
00119        "This service reports the time it takes to run each module in a job.");
00120     }
00121 
00122     void Timing::postBeginJob() {
00123       curr_job_time_ = getTime();
00124       curr_job_cpu_ = getCPU();
00125       total_event_cpu_ = 0.0;
00126 
00127       //LogInfo("TimeReport")
00128       if (not summary_only_) {
00129         LogImportant("TimeReport")                              // ChangeLog 3
00130         << "TimeReport> Report activated" << "\n"
00131         << "TimeReport> Report columns headings for events: "
00132         << "eventnum runnum timetaken\n"
00133         << "TimeReport> Report columns headings for modules: "
00134         << "eventnum runnum modulelabel modulename timetakeni\n"
00135         << "TimeReport> JobTime=" << curr_job_time_  << " JobCPU=" << curr_job_cpu_  << "\n";
00136       }
00137     }
00138 
00139     void Timing::postEndJob() {
00140       double total_job_time = getTime() - curr_job_time_;
00141       double average_event_time = total_job_time / total_event_count_;
00142 
00143       double total_job_cpu = getCPU() - curr_job_cpu_;
00144       double average_event_cpu = total_event_cpu_ / total_event_count_;
00145 
00146       //LogAbsolute("FwkJob")
00147       //LogAbsolute("TimeReport")                               // Changelog 1
00148       LogImportant("TimeReport")                                // Changelog 3
00149         << "TimeReport> Time report complete in "
00150         << total_job_time << " seconds"
00151         << "\n"
00152         << " Time Summary: \n"
00153         << " - Min event:   " << min_event_time_ << "\n"
00154         << " - Max event:   " << max_event_time_ << "\n"
00155         << " - Avg event:   " << average_event_time << "\n"
00156         << " - Total job:   " << total_job_time << "\n"
00157         << " CPU Summary: \n"
00158         << " - Min event:   " << min_event_cpu_ << "\n"
00159         << " - Max event:   " << max_event_cpu_ << "\n"
00160         << " - Avg event:   " << average_event_cpu << "\n"
00161         << " - Total job:   " << total_job_cpu << "\n"
00162         << " - Total event: " << total_event_cpu_ << "\n";
00163 
00164       if (report_summary_) {
00165         Service<JobReport> reportSvc;
00166 //      std::map<std::string, double> reportData;
00167         std::map<std::string, std::string> reportData;
00168 
00169         reportData.insert(std::make_pair("MinEventTime", d2str(min_event_time_)));
00170         reportData.insert(std::make_pair("MaxEventTime", d2str(max_event_time_)));
00171         reportData.insert(std::make_pair("AvgEventTime", d2str(average_event_time)));
00172         reportData.insert(std::make_pair("TotalJobTime", d2str(total_job_time)));
00173         reportData.insert(std::make_pair("MinEventCPU", d2str(min_event_cpu_)));
00174         reportData.insert(std::make_pair("MaxEventCPU", d2str(max_event_cpu_)));
00175         reportData.insert(std::make_pair("AvgEventCPU", d2str(average_event_cpu)));
00176         reportData.insert(std::make_pair("TotalJobCPU", d2str(total_job_cpu)));
00177         reportData.insert(std::make_pair("TotalEventCPU", d2str(total_event_cpu_)));
00178         
00179         reportSvc->reportPerformanceSummary("Timing", reportData);
00180 //      reportSvc->reportTimingInfo(reportData);
00181       }
00182     }
00183 
00184     void Timing::preEventProcessing(EventID const& iID, Timestamp const& iTime) {
00185       curr_event_ = iID;
00186       curr_event_time_ = getTime();
00187       curr_event_cpu_ = getCPU();
00188     }
00189 
00190     void Timing::postEventProcessing(Event const& e, EventSetup const&) {
00191       curr_event_cpu_ = getCPU() - curr_event_cpu_;
00192       total_event_cpu_ += curr_event_cpu_;
00193 
00194       curr_event_time_ = getTime() - curr_event_time_;
00195 
00196       if (not summary_only_) {
00197         LogPrint("TimeEvent")                           // ChangeLog 3
00198         << "TimeEvent> "
00199         << curr_event_.event() << " "
00200         << curr_event_.run() << " "
00201         << curr_event_time_ << " "
00202         << curr_event_cpu_ << " "
00203         << total_event_cpu_;
00204       }
00205       if (total_event_count_ == 0) {
00206         max_event_time_ = curr_event_time_;
00207         min_event_time_ = curr_event_time_;
00208         max_event_cpu_ = curr_event_cpu_;
00209         min_event_cpu_ = curr_event_cpu_;
00210       }
00211 
00212       if (curr_event_time_ > max_event_time_) max_event_time_ = curr_event_time_;
00213       if (curr_event_time_ < min_event_time_) min_event_time_ = curr_event_time_;
00214       if (curr_event_cpu_ > max_event_cpu_) max_event_cpu_ = curr_event_cpu_;
00215       if (curr_event_cpu_ < min_event_cpu_) min_event_cpu_ = curr_event_cpu_;
00216       total_event_count_ = total_event_count_ + 1;
00217     }
00218 
00219     void Timing::preModule(ModuleDescription const&) {
00220       curr_module_time_ = getTime();
00221     }
00222 
00223     void Timing::postModule(ModuleDescription const& desc) {
00224       double t = getTime() - curr_module_time_;
00225       //LogInfo("TimeModule")
00226       if (not summary_only_) {
00227         LogPrint("TimeModule") << "TimeModule> "                // ChangeLog 4
00228            << curr_event_.event() << " "
00229            << curr_event_.run() << " "
00230            << desc.moduleLabel() << " "
00231            << desc.moduleName() << " "
00232            << t;
00233       }
00234 
00235     }
00236   }
00237 }
00238