32 #include <sys/resource.h>
39 namespace eventsetup {
40 struct ComponentDescription;
100 void accumulateTimeBegin(std::atomic<CountAndTime*>& countAndTime,
double& accumulatedTime);
101 void accumulateTimeEnd(std::atomic<CountAndTime*>& countAndTime,
double& accumulatedTime);
159 if (gettimeofday(&
t,
nullptr) < 0)
160 throw cms::Exception(
"SysCallFailed",
"Failed call to gettimeofday");
161 return static_cast<double>(
t.tv_sec) + (static_cast<double>(
t.tv_usec) * 1E-6);
166 getrusage(RUSAGE_SELF, &
usage);
168 double totalCPUTime = 0.0;
170 totalCPUTime = (double)
usage.ru_utime.tv_sec + (
double(
usage.ru_utime.tv_usec) * 1E-6);
172 totalCPUTime += (double)
usage.ru_stime.tv_sec + (
double(
usage.ru_stime.tv_usec) * 1E-6);
175 getrusage(RUSAGE_CHILDREN, &
usage);
176 totalCPUTime += (double)
usage.ru_utime.tv_sec + (
double(
usage.ru_utime.tv_usec) * 1E-6);
177 totalCPUTime += (double)
usage.ru_stime.tv_sec + (
double(
usage.ru_stime.tv_usec) * 1E-6);
186 static thread_local std::vector<double> s_stack;
192 assert(!modStack.empty());
193 double curr_module_time = modStack.back();
195 double t =
getTime() - curr_module_time;
199 static void pushStack(
bool configuredInTopLevelProcess) {
200 if (!configuredInTopLevelProcess) {
208 : curr_job_time_(0.),
214 summary_only_(iPS.getUntrackedParameter<
bool>(
"summaryOnly")),
215 report_summary_(iPS.getUntrackedParameter<
bool>(
"useJobReport")),
216 threshold_(iPS.getUntrackedParameter<double>(
"excessiveTimeThreshold")),
219 total_event_count_(0),
220 begin_lumi_count_(0),
222 countAndTimeZero_{0, 0.0},
223 countAndTimeForLock_{&countAndTimeZero_},
224 accumulatedTimeForLock_{0.0},
225 countAndTimeForGet_{&countAndTimeZero_},
226 accumulatedTimeForGet_{0.0},
227 configuredInTopLevelProcess_{
false},
236 bool checkThreshold =
true;
237 if (threshold_ <= 0.0) {
240 checkThreshold =
false;
243 if ((not summary_only_) || (checkThreshold)) {
247 if (checkThreshold) {
299 iRegistry.preallocateSignal_.connect([
this](service::SystemBounds
const& iBounds) {
300 nStreams_ = iBounds.maxNumberOfStreams();
301 nThreads_ = iBounds.maxNumberOfThreads();
302 curr_events_time_.resize(nStreams_, 0.);
303 sum_events_time_.resize(nStreams_, 0.);
304 max_events_time_.resize(nStreams_, 0.);
305 min_events_time_.resize(nStreams_, 1.E6);
306 for (
unsigned int i = 0;
i < nStreams_; ++
i) {
307 countSubProcessesPreEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
308 countSubProcessesPostEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
323 while (not
extra_job_cpu_.compare_exchange_strong(expected, expected + iTime)) {
331 desc.addUntracked<
bool>(
"summaryOnly",
false)->setComment(
"If 'true' do not report timing for each event");
332 desc.addUntracked<
bool>(
"useJobReport",
true)->setComment(
"If 'true' write summary information to JobReport");
333 desc.addUntracked<
double>(
"excessiveTimeThreshold", 0.)
335 "Amount of time in seconds before reporting a module or source has taken excessive time. A value of 0.0 "
336 "turns off this reporting.");
337 descriptions.
add(
"Timing",
desc);
338 descriptions.
setComment(
"This service reports the time it takes to run each module in a job.");
357 LogImportant(
"TimeReport") <<
"TimeReport> Report activated"
359 <<
"TimeReport> Report columns headings for events: "
360 <<
"eventnum runnum timetaken\n"
361 <<
"TimeReport> Report columns headings for modules: "
362 <<
"eventnum runnum modulelabel modulename timetakeni\n"
369 LogImportant(
"TimeReport") <<
"\nTimeReport> This instance of the Timing Service will be disabled because it "
370 "is configured in a SubProcess.\n"
371 <<
"If multiple instances of the TimingService were configured only the one in the "
372 "top level process will function.\n"
373 <<
"The other instance(s) will simply print this message and do nothing.\n\n";
377 const double job_end_time =
getTime();
378 const double job_end_cpu =
getCPU();
399 total_loop_time = 0.0;
400 total_loop_cpu = 0.0;
403 double sum_all_events_time = 0;
405 sum_all_events_time +=
t;
408 double average_event_time = 0.0;
413 double event_throughput = 0.0;
414 if (total_loop_time != 0.0) {
418 LogImportant(
"TimeReport") <<
"TimeReport> Time report complete in " << total_job_time <<
" seconds"
420 <<
" Time Summary: \n"
421 <<
" - Min event: " << min_event_time <<
"\n"
422 <<
" - Max event: " << max_event_time <<
"\n"
423 <<
" - Avg event: " << average_event_time <<
"\n"
424 <<
" - Total loop: " << total_loop_time <<
"\n"
425 <<
" - Total init: " << total_initialization_time <<
"\n"
426 <<
" - Total job: " << total_job_time <<
"\n"
429 <<
" Event Throughput: " << event_throughput <<
" ev/s\n"
430 <<
" CPU Summary: \n"
431 <<
" - Total loop: " << total_loop_cpu <<
"\n"
432 <<
" - Total init: " << total_initialization_cpu <<
"\n"
434 <<
" - Total job: " << total_job_cpu <<
"\n"
435 <<
" Processing Summary: \n"
442 std::map<std::string, std::string> reportData;
444 reportData.insert(std::make_pair(
"MinEventTime",
d2str(min_event_time)));
445 reportData.insert(std::make_pair(
"MaxEventTime",
d2str(max_event_time)));
446 reportData.insert(std::make_pair(
"AvgEventTime",
d2str(average_event_time)));
447 reportData.insert(std::make_pair(
"EventThroughput",
d2str(event_throughput)));
448 reportData.insert(std::make_pair(
"TotalJobTime",
d2str(total_job_time)));
449 reportData.insert(std::make_pair(
"TotalJobCPU",
d2str(total_job_cpu)));
450 reportData.insert(std::make_pair(
"TotalLoopTime",
d2str(total_loop_time)));
451 reportData.insert(std::make_pair(
"TotalLoopCPU",
d2str(total_loop_cpu)));
452 reportData.insert(std::make_pair(
"TotalInitTime",
d2str(total_initialization_time)));
453 reportData.insert(std::make_pair(
"TotalInitCPU",
d2str(total_initialization_cpu)));
454 reportData.insert(std::make_pair(
"NumberOfStreams",
ui2str(
nStreams_)));
455 reportData.insert(std::make_pair(
"NumberOfThreads",
ui2str(
nThreads_)));
458 reportSvc->reportPerformanceSummary(
"Timing", reportData);
460 std::map<std::string, std::string> reportData1;
464 reportSvc->reportPerformanceSummary(
"ProcessingSummary", reportData1);
505 auto const& eventID = iStream.
eventID();
506 LogPrint(
"TimeEvent") <<
"TimeEvent> " << eventID.event() <<
" " << eventID.run() <<
" " << curr_event_time;
519 auto const& eventID = iStream.
eventID();
523 LogPrint(
"TimeModule") <<
"TimeModule> " << eventID.event() <<
" " << eventID.run() <<
" " <<
desc.moduleLabel()
524 <<
" " <<
desc.moduleName() <<
" " <<
t;
585 <<
"ExcessiveTime: Module used " <<
t
586 <<
" seconds of time which exceeds the error threshold configured in the Timing Service of " <<
threshold_
594 auto newStat = std::make_unique<CountAndTime>(0, newTime);
598 if (oldStat ==
nullptr) {
599 oldStat = countAndTime.load();
600 }
else if (countAndTime.compare_exchange_strong(oldStat,
nullptr)) {
606 if (oldStat->
count_ != 0) {
607 accumulatedTime += (newTime - oldStat->
time_) * oldStat->
count_;
609 countAndTime.store(newStat.release());
620 if (oldStat ==
nullptr) {
621 oldStat = countAndTime.load();
622 }
else if (countAndTime.compare_exchange_strong(oldStat,
nullptr)) {
627 if (oldStat->
count_ == 1) {
628 accumulatedTime += newTime - oldStat->
time_;
632 auto newStat = std::make_unique<CountAndTime>(oldStat->
count_ - 1, newTime);
633 accumulatedTime += (newTime - oldStat->
time_) * oldStat->
count_;
634 countAndTime.store(newStat.release());
636 countAndTime.store(oldStat);