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