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 #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
00075 totalCPUTime = (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6);
00076
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
00128 if (not summary_only_) {
00129 LogImportant("TimeReport")
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
00147
00148 LogImportant("TimeReport")
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
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
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")
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
00226 if (not summary_only_) {
00227 LogPrint("TimeModule") << "TimeModule> "
00228 << curr_event_.event() << " "
00229 << curr_event_.run() << " "
00230 << desc.moduleLabel() << " "
00231 << desc.moduleName() << " "
00232 << t;
00233 }
00234
00235 }
00236 }
00237 }
00238