32 #include <sys/resource.h> 39 namespace eventsetup {
40 struct ComponentDescription;
53 void addToCPUTime(
double iTime)
override;
54 double getTotalCPU()
const override;
64 void lastPostEvent(
double curr_event_time,
unsigned int index,
StreamContext const& iStream);
92 double postCommon()
const;
113 void accumulateTimeBegin(std::atomic<CountAndTime*>& countAndTime,
double& accumulatedTime);
114 void accumulateTimeEnd(std::atomic<CountAndTime*>& countAndTime,
double& accumulatedTime);
146 std::vector<
std::unique_ptr<
std::atomic<
unsigned int>>> countSubProcessesPreEvent_;
147 std::vector<
std::unique_ptr<
std::atomic<
unsigned int>>> countSubProcessesPostEvent_;
149 bool configuredInTopLevelProcess_;
150 unsigned int nSubProcesses_;
173 if(gettimeofday(&t,
nullptr) < 0)
174 throw cms::Exception(
"SysCallFailed",
"Failed call to gettimeofday");
175 return static_cast<double>(t.tv_sec) + (static_cast<double>(t.tv_usec) * 1E-6);
180 getrusage(RUSAGE_SELF, &usage);
182 double totalCPUTime = 0.0;
184 totalCPUTime = (double)usage.ru_utime.tv_sec + (
double(usage.ru_utime.tv_usec) * 1E-6);
186 totalCPUTime += (double)usage.ru_stime.tv_sec + (
double(usage.ru_stime.tv_usec) * 1E-6);
189 getrusage(RUSAGE_CHILDREN, &usage);
190 totalCPUTime += (double)usage.ru_utime.tv_sec + (
double(usage.ru_utime.tv_usec) * 1E-6);
191 totalCPUTime += (double)usage.ru_stime.tv_sec + (
double(usage.ru_stime.tv_usec) * 1E-6);
201 static thread_local std::vector<double> s_stack;
208 assert(!modStack.empty());
209 double curr_module_time = modStack.back();
211 double t =
getTime() - curr_module_time;
217 if (!configuredInTopLevelProcess) {
231 summary_only_(iPS.getUntrackedParameter<
bool>(
"summaryOnly")),
232 report_summary_(iPS.getUntrackedParameter<
bool>(
"useJobReport")),
233 threshold_(iPS.getUntrackedParameter<double>(
"excessiveTimeThreshold")),
236 total_event_count_(0),
237 begin_lumi_count_(0),
239 countAndTimeZero_{0, 0.0},
240 countAndTimeForLock_{&countAndTimeZero_},
241 accumulatedTimeForLock_{0.0},
242 countAndTimeForGet_{&countAndTimeZero_},
243 accumulatedTimeForGet_{0.0},
244 configuredInTopLevelProcess_{
false},
258 bool checkThreshold =
true;
259 if (threshold_ <= 0.0) {
262 checkThreshold =
false;
265 if( (not summary_only_) || (checkThreshold) ) {
321 iRegistry.preallocateSignal_.connect([
this](service::SystemBounds
const& iBounds){
322 nStreams_ = iBounds.maxNumberOfStreams();
323 nThreads_ = iBounds.maxNumberOfThreads();
324 curr_events_time_.resize(nStreams_,0.);
325 sum_events_time_.resize(nStreams_,0.);
326 max_events_time_.resize(nStreams_,0.);
327 min_events_time_.resize(nStreams_,1.E6);
328 for (
unsigned int i = 0;
i < nStreams_; ++
i) {
329 countSubProcessesPreEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
330 countSubProcessesPostEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
345 double expected = extra_job_cpu_.load();
346 while( not extra_job_cpu_.compare_exchange_strong(expected,expected+iTime) ) {}
355 desc.
addUntracked<
bool>(
"summaryOnly",
false)->setComment(
356 "If 'true' do not report timing for each event");
357 desc.
addUntracked<
bool>(
"useJobReport",
true)->setComment(
358 "If 'true' write summary information to JobReport");
360 "Amount of time in seconds before reporting a module or source has taken excessive time. A value of 0.0 turns off this reporting.");
361 descriptions.
add(
"Timing", desc);
363 "This service reports the time it takes to run each module in a job.");
370 configuredInTopLevelProcess_ =
true;
375 if (!configuredInTopLevelProcess_) {
381 if(not summary_only_) {
383 <<
"TimeReport> Report activated" <<
"\n" 384 <<
"TimeReport> Report columns headings for events: " 385 <<
"eventnum runnum timetaken\n" 386 <<
"TimeReport> Report columns headings for modules: " 387 <<
"eventnum runnum modulelabel modulename timetakeni\n" 388 <<
"TimeReport> JobTime=" << curr_job_time_ <<
" JobCPU=" << curr_job_cpu_ <<
"\n";
394 if (!configuredInTopLevelProcess_) {
395 LogImportant(
"TimeReport") <<
"\nTimeReport> This instance of the Timing Service will be disabled because it is configured in a SubProcess.\n" 396 <<
"If multiple instances of the TimingService were configured only the one in the top level process will function.\n" 397 <<
"The other instance(s) will simply print this message and do nothing.\n\n";
401 const double job_end_time =
getTime();
402 const double job_end_cpu =
getCPU();
407 const double total_initialization_time = curr_job_time_ -
jobStartTime();
413 total_job_cpu =job_end_cpu + extra_job_cpu_ -
curr_job_cpu_ ;
416 double min_event_time = *(std::min_element(min_events_time_.begin(),
417 min_events_time_.end()));
418 double max_event_time = *(std::max_element(max_events_time_.begin(),
419 max_events_time_.end()));
422 auto total_loop_cpu = last_run_cpu_ + extra_job_cpu_ -
curr_job_cpu_;
424 if(last_run_time_ == 0.0) {
425 total_loop_time = 0.0;
426 total_loop_cpu = 0.0;
429 double sum_all_events_time = 0;
430 for(
auto t : sum_events_time_) { sum_all_events_time +=
t; }
432 double average_event_time = 0.0;
433 if(total_event_count_ != 0) {
437 double event_throughput = 0.0;
438 if(total_loop_time != 0.0) {
439 event_throughput = total_event_count_ / total_loop_time;
443 <<
"TimeReport> Time report complete in " 444 << total_job_time <<
" seconds" 446 <<
" Time Summary: \n" 447 <<
" - Min event: " << min_event_time <<
"\n" 448 <<
" - Max event: " << max_event_time <<
"\n" 449 <<
" - Avg event: " << average_event_time <<
"\n" 450 <<
" - Total loop: " << total_loop_time <<
"\n" 451 <<
" - Total init: " << total_initialization_time <<
"\n" 452 <<
" - Total job: " << total_job_time <<
"\n" 453 <<
" - EventSetup Lock: " << accumulatedTimeForLock_ <<
"\n" 454 <<
" - EventSetup Get: " << accumulatedTimeForGet_ <<
"\n" 455 <<
" Event Throughput: "<< event_throughput <<
" ev/s\n" 456 <<
" CPU Summary: \n" 457 <<
" - Total loop: " << total_loop_cpu <<
"\n" 458 <<
" - Total init: " << total_initialization_cpu <<
"\n" 459 <<
" - Total extra: " << extra_job_cpu_ <<
"\n" 460 <<
" - Total job: " << total_job_cpu <<
"\n" 461 <<
" Processing Summary: \n" 462 <<
" - Number of Events: " << total_event_count_ <<
"\n" 463 <<
" - Number of Global Begin Lumi Calls: " << begin_lumi_count_ <<
"\n" 464 <<
" - Number of Global Begin Run Calls: " << begin_run_count_ <<
"\n";
466 if(report_summary_) {
468 std::map<std::string, std::string> reportData;
470 reportData.insert(std::make_pair(
"MinEventTime",
d2str(min_event_time)));
471 reportData.insert(std::make_pair(
"MaxEventTime",
d2str(max_event_time)));
472 reportData.insert(std::make_pair(
"AvgEventTime",
d2str(average_event_time)));
473 reportData.insert(std::make_pair(
"EventThroughput",
d2str(event_throughput)));
474 reportData.insert(std::make_pair(
"TotalJobTime",
d2str(total_job_time)));
475 reportData.insert(std::make_pair(
"TotalJobCPU",
d2str(total_job_cpu)));
476 reportData.insert(std::make_pair(
"TotalLoopTime",
d2str(total_loop_time)));
477 reportData.insert(std::make_pair(
"TotalLoopCPU",
d2str(total_loop_cpu)));
478 reportData.insert(std::make_pair(
"TotalInitTime",
d2str(total_initialization_time)));
479 reportData.insert(std::make_pair(
"TotalInitCPU",
d2str(total_initialization_cpu)));
480 reportData.insert(std::make_pair(
"NumberOfStreams",
ui2str(nStreams_)));
481 reportData.insert(std::make_pair(
"NumberOfThreads",
ui2str(nThreads_)));
482 reportData.insert(std::make_pair(
"EventSetup Lock",
d2str(accumulatedTimeForLock_)));
483 reportData.insert(std::make_pair(
"EventSetup Get",
d2str(accumulatedTimeForGet_)));
484 reportSvc->reportPerformanceSummary(
"Timing", reportData);
486 std::map<std::string, std::string> reportData1;
487 reportData1.insert(std::make_pair(
"NumberEvents",
ui2str(total_event_count_)));
488 reportData1.insert(std::make_pair(
"NumberBeginLumiCalls",
ui2str(begin_lumi_count_)));
489 reportData1.insert(std::make_pair(
"NumberBeginRunCalls",
ui2str(begin_run_count_)));
490 reportSvc->reportPerformanceSummary(
"ProcessingSummary", reportData1);
495 if (!configuredInTopLevelProcess_) {
499 if (nSubProcesses_ == 0u) {
502 unsigned int count = ++(*countSubProcessesPreEvent_[
index]);
505 }
else if (count == (nSubProcesses_ + 1)) {
506 *countSubProcessesPreEvent_[
index] = 0;
512 if (!configuredInTopLevelProcess_) {
516 if (nSubProcesses_ == 0u) {
519 unsigned int count = ++(*countSubProcessesPostEvent_[
index]);
520 if (count == (nSubProcesses_ + 1)) {
522 *countSubProcessesPostEvent_[
index] = 0;
528 sum_events_time_[
index] +=curr_event_time;
530 if(not summary_only_) {
531 auto const & eventID = iStream.
eventID();
534 << eventID.event() <<
" " 535 << eventID.run() <<
" " 538 if(curr_event_time > max_events_time_[index]) max_events_time_[
index] = curr_event_time;
539 if(curr_event_time < min_events_time_[index]) min_events_time_[
index] = curr_event_time;
544 if (!configuredInTopLevelProcess_) {
547 auto const & eventID = iStream.
eventID();
550 if ( not summary_only_) {
551 LogPrint(
"TimeModule") <<
"TimeModule> " 552 << eventID.event() <<
" " 553 << eventID.run() <<
" " 554 << desc.moduleLabel() <<
" " 555 << desc.moduleName() <<
" " 614 if (!configuredInTopLevelProcess_) {
624 if (!configuredInTopLevelProcess_) {
644 if (!configuredInTopLevelProcess_) {
650 <<
"ExcessiveTime: Module used " << t
651 <<
" seconds of time which exceeds the error threshold configured in the Timing Service of " 652 << threshold_ <<
" seconds.";
662 if (!configuredInTopLevelProcess_) {
673 if (!configuredInTopLevelProcess_) {
692 auto newStat = std::make_unique<CountAndTime>(0, newTime);
696 if (oldStat ==
nullptr) {
697 oldStat = countAndTime.load();
698 }
else if (countAndTime.compare_exchange_strong(oldStat,
nullptr)) {
703 newStat->
count_ = oldStat->count_ + 1;
704 if (oldStat->count_ != 0) {
705 accumulatedTime += (newTime - oldStat->time_) * oldStat->count_;
707 countAndTime.store(newStat.release());
708 if (oldStat != &countAndTimeZero_) {
720 if (oldStat ==
nullptr) {
721 oldStat = countAndTime.load();
722 }
else if (countAndTime.compare_exchange_strong(oldStat,
nullptr)) {
727 if (oldStat->
count_ == 1) {
728 accumulatedTime += newTime - oldStat->
time_;
729 countAndTime.store(&countAndTimeZero_);
732 auto newStat = std::make_unique<CountAndTime>(oldStat->
count_ - 1, newTime);
733 accumulatedTime += (newTime - oldStat->
time_) * oldStat->
count_;
734 countAndTime.store(newStat.release());
736 countAndTime.store(oldStat);
std::vector< double > sum_events_time_
void setComment(std::string const &value)
std::atomic< double > last_run_cpu_
#define DEFINE_FWK_SERVICE_MAKER(concrete, maker)
std::vector< double > max_events_time_
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
std::vector< double > curr_events_time_
void postLockEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
double getTotalCPU() const override
void preModule(ModuleDescription const &md)
void postEvent(StreamContext const &)
void preModuleStream(StreamContext const &, ModuleCallingContext const &)
std::atomic< unsigned long > begin_lumi_count_
edm::serviceregistry::AllArgsMaker< edm::TimingServiceBase, Timing > TimingMaker
void lastPostEvent(double curr_event_time, unsigned int index, StreamContext const &iStream)
void accumulateTimeBegin(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
void preSourceLumi(LuminosityBlockIndex)
void preOpenFile(std::string const &, bool)
void preModuleGlobal(GlobalContext const &, ModuleCallingContext const &)
void postModule(ModuleDescription const &md)
void postGlobalBeginRun(GlobalContext const &)
void preSourceRun(RunIndex)
void postModuleStream(StreamContext const &, ModuleCallingContext const &)
void accumulateTimeEnd(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
CountAndTime(unsigned int count, double time)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
ModuleDescription const * moduleDescription() const
void postModuleEvent(StreamContext const &, ModuleCallingContext const &)
#define CMS_THREAD_GUARD(_var_)
std::atomic< double > last_run_time_
void postSourceLumi(LuminosityBlockIndex)
static void pushStack(bool configuredInTopLevelProcess)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::atomic< CountAndTime * > countAndTimeForLock_
void preLockEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
static double jobStartTime()
StreamID const & streamID() const
static std::string ui2str(unsigned int i)
void setComment(std::string const &value)
void postGlobalBeginLumi(GlobalContext const &)
std::atomic< unsigned long > begin_run_count_
unsigned int value() const
void postEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
std::atomic< unsigned long > total_event_count_
static std::vector< double > & moduleTimeStack()
void addToCPUTime(double iTime) override
static std::string d2str(double d)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
double postCommon() const
ProcessContext const * processContext() const
void postSourceRun(RunIndex)
void postModuleGlobal(GlobalContext const &, ModuleCallingContext const &)
void preBeginJob(PathsAndConsumesOfModulesBase const &, ProcessContext const &)
CountAndTime countAndTimeZero_
void postOpenFile(std::string const &, bool)
void postSourceEvent(StreamID)
EventID const & eventID() const
std::atomic< double > extra_job_cpu_
bool isSubProcess() const
void preSourceEvent(StreamID)
void preEvent(StreamContext const &)
std::vector< double > min_events_time_
unsigned int nSubProcesses_