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);
167 getrusage(RUSAGE_CHILDREN, &usage);
168 double totalCPUTime = (double)usage.ru_utime.tv_sec + (
double(usage.ru_utime.tv_usec) * 1E-6);
169 totalCPUTime += (double)usage.ru_stime.tv_sec + (
double(usage.ru_stime.tv_usec) * 1E-6);
176 getrusage(RUSAGE_SELF, &usage);
178 double totalCPUTime = 0.0;
180 totalCPUTime = (double)usage.ru_utime.tv_sec + (
double(usage.ru_utime.tv_usec) * 1E-6);
182 totalCPUTime += (double)usage.ru_stime.tv_sec + (
double(usage.ru_stime.tv_usec) * 1E-6);
185 getrusage(RUSAGE_CHILDREN, &usage);
186 totalCPUTime += (double)usage.ru_utime.tv_sec + (
double(usage.ru_utime.tv_usec) * 1E-6);
187 totalCPUTime += (double)usage.ru_stime.tv_sec + (
double(usage.ru_stime.tv_usec) * 1E-6);
196 static thread_local std::vector<double> s_stack;
202 assert(!modStack.empty());
203 double curr_module_time = modStack.back();
205 double t =
getTime() - curr_module_time;
209 static void pushStack(
bool configuredInTopLevelProcess) {
210 if (!configuredInTopLevelProcess) {
224 summary_only_(iPS.getUntrackedParameter<bool>(
"summaryOnly")),
226 threshold_(iPS.getUntrackedParameter<double>(
"excessiveTimeThreshold")),
233 countAndTimeForLock_{&countAndTimeZero_},
234 accumulatedTimeForLock_{0.0},
235 countAndTimeForGet_{&countAndTimeZero_},
236 accumulatedTimeForGet_{0.0},
237 configuredInTopLevelProcess_{
false},
241 iRegistry.preEndJobSignal_.connect([
this]() {
250 bool checkThreshold =
true;
251 if (threshold_ <= 0.0) {
254 checkThreshold =
false;
257 if ((not summary_only_) || (checkThreshold)) {
261 if (checkThreshold) {
316 iRegistry.preallocateSignal_.connect([
this](service::SystemBounds
const& iBounds) {
317 nStreams_ = iBounds.maxNumberOfStreams();
318 nThreads_ = iBounds.maxNumberOfThreads();
319 curr_events_time_.resize(nStreams_, 0.);
320 sum_events_time_.resize(nStreams_, 0.);
321 max_events_time_.resize(nStreams_, 0.);
322 min_events_time_.resize(nStreams_, 1.E6);
323 for (
unsigned int i = 0;
i < nStreams_; ++
i) {
324 countSubProcessesPreEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
325 countSubProcessesPostEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
335 while (not
extra_job_cpu_.compare_exchange_strong(expected, expected + iTime)) {
343 desc.
addUntracked<
bool>(
"summaryOnly",
false)->setComment(
"If 'true' do not report timing for each event");
344 desc.
addUntracked<
bool>(
"useJobReport",
true)->setComment(
"If 'true' write summary information to JobReport");
347 "Amount of time in seconds before reporting a module or source has taken excessive time. A value of 0.0 "
348 "turns off this reporting.");
349 descriptions.
add(
"Timing", desc);
350 descriptions.
setComment(
"This service reports the time it takes to run each module in a job.");
357 configuredInTopLevelProcess_ =
true;
362 if (!configuredInTopLevelProcess_) {
368 if (not summary_only_) {
369 LogImportant(
"TimeReport") <<
"TimeReport> Report activated"
371 <<
"TimeReport> Report columns headings for events: "
372 <<
"eventnum runnum timetaken\n"
373 <<
"TimeReport> Report columns headings for modules: "
374 <<
"eventnum runnum modulelabel modulename timetakeni\n"
380 if (!configuredInTopLevelProcess_) {
381 LogImportant(
"TimeReport") <<
"\nTimeReport> This instance of the Timing Service will be disabled because it "
382 "is configured in a SubProcess.\n"
383 <<
"If multiple instances of the TimingService were configured only the one in the "
384 "top level process will function.\n"
385 <<
"The other instance(s) will simply print this message and do nothing.\n\n";
389 const double job_end_time =
getTime();
390 const double job_end_cpu =
getCPU();
403 total_job_cpu = job_end_cpu + extra_job_cpu_ -
curr_job_cpu_;
413 total_loop_time = 0.0;
414 total_loop_cpu = 0.0;
417 double sum_all_events_time = 0;
419 sum_all_events_time +=
t;
422 double average_event_time = 0.0;
427 double event_throughput = 0.0;
428 if (total_loop_time != 0.0) {
432 LogImportant(
"TimeReport") <<
"TimeReport> Time report complete in " << total_job_time <<
" seconds"
434 <<
" Time Summary: \n"
435 <<
" - Min event: " << min_event_time <<
"\n"
436 <<
" - Max event: " << max_event_time <<
"\n"
437 <<
" - Avg event: " << average_event_time <<
"\n"
438 <<
" - Total loop: " << total_loop_time <<
"\n"
439 <<
" - Total init: " << total_initialization_time <<
"\n"
440 <<
" - Total job: " << total_job_time <<
"\n"
441 <<
" - EventSetup Lock: " << accumulatedTimeForLock_ <<
"\n"
442 <<
" - EventSetup Get: " << accumulatedTimeForGet_ <<
"\n"
443 <<
" Event Throughput: " << event_throughput <<
" ev/s\n"
444 <<
" CPU Summary: \n"
445 <<
" - Total loop: " << total_loop_cpu <<
"\n"
446 <<
" - Total init: " << total_initialization_cpu <<
"\n"
447 <<
" - Total extra: " << extra_job_cpu_ <<
"\n"
448 <<
" - Total children: " << job_end_children_cpu <<
"\n"
449 <<
" - Total job: " << total_job_cpu <<
"\n"
450 <<
" Processing Summary: \n"
457 std::map<std::string, std::string> reportData;
459 reportData.insert(std::make_pair(
"MinEventTime",
d2str(min_event_time)));
460 reportData.insert(std::make_pair(
"MaxEventTime",
d2str(max_event_time)));
461 reportData.insert(std::make_pair(
"AvgEventTime",
d2str(average_event_time)));
462 reportData.insert(std::make_pair(
"EventThroughput",
d2str(event_throughput)));
463 reportData.insert(std::make_pair(
"TotalJobTime",
d2str(total_job_time)));
464 reportData.insert(std::make_pair(
"TotalJobCPU",
d2str(total_job_cpu)));
465 reportData.insert(std::make_pair(
"TotalJobChildrenCPU",
d2str(job_end_children_cpu)));
466 reportData.insert(std::make_pair(
"TotalLoopTime",
d2str(total_loop_time)));
467 reportData.insert(std::make_pair(
"TotalLoopCPU",
d2str(total_loop_cpu)));
468 reportData.insert(std::make_pair(
"TotalInitTime",
d2str(total_initialization_time)));
469 reportData.insert(std::make_pair(
"TotalInitCPU",
d2str(total_initialization_cpu)));
470 reportData.insert(std::make_pair(
"NumberOfStreams",
ui2str(nStreams_)));
471 reportData.insert(std::make_pair(
"NumberOfThreads",
ui2str(
nThreads_)));
472 reportData.insert(std::make_pair(
"EventSetup Lock",
d2str(accumulatedTimeForLock_)));
473 reportData.insert(std::make_pair(
"EventSetup Get",
d2str(accumulatedTimeForGet_)));
474 reportSvc->reportPerformanceSummary(
"Timing", reportData);
476 std::map<std::string, std::string> reportData1;
479 reportData1.insert(std::make_pair(
"NumberBeginRunCalls",
ui2str(begin_run_count_)));
480 reportSvc->reportPerformanceSummary(
"ProcessingSummary", reportData1);
485 if (!configuredInTopLevelProcess_) {
489 if (nSubProcesses_ == 0u) {
492 unsigned int count = ++(*countSubProcessesPreEvent_[
index]);
495 }
else if (count == (nSubProcesses_ + 1)) {
496 *countSubProcessesPreEvent_[
index] = 0;
502 if (!configuredInTopLevelProcess_) {
506 if (nSubProcesses_ == 0u) {
509 unsigned int count = ++(*countSubProcessesPostEvent_[
index]);
510 if (count == (nSubProcesses_ + 1)) {
512 *countSubProcessesPostEvent_[
index] = 0;
520 if (not summary_only_) {
521 auto const& eventID = iStream.
eventID();
522 LogPrint(
"TimeEvent") <<
"TimeEvent> " << eventID.event() <<
" " << eventID.run() <<
" " << curr_event_time;
532 if (!configuredInTopLevelProcess_) {
535 auto const& eventID = iStream.
eventID();
538 if (not summary_only_) {
539 LogPrint(
"TimeModule") <<
"TimeModule> " << eventID.event() <<
" " << eventID.run() <<
" " <<
desc.moduleLabel()
540 <<
" " <<
desc.moduleName() <<
" " <<
t;
571 if (!configuredInTopLevelProcess_) {
580 if (!configuredInTopLevelProcess_) {
595 if (!configuredInTopLevelProcess_) {
601 <<
"ExcessiveTime: Module used " << t
602 <<
" seconds of time which exceeds the error threshold configured in the Timing Service of " <<
threshold_
610 auto newStat = std::make_unique<CountAndTime>(0, newTime);
614 if (oldStat ==
nullptr) {
615 oldStat = countAndTime.load();
616 }
else if (countAndTime.compare_exchange_strong(oldStat,
nullptr)) {
621 newStat->
count_ = oldStat->count_ + 1;
622 if (oldStat->count_ != 0) {
623 accumulatedTime += (newTime - oldStat->time_) * oldStat->count_;
625 countAndTime.store(newStat.release());
636 if (oldStat ==
nullptr) {
637 oldStat = countAndTime.load();
638 }
else if (countAndTime.compare_exchange_strong(oldStat,
nullptr)) {
643 if (oldStat->
count_ == 1) {
644 accumulatedTime += newTime - oldStat->
time_;
648 auto newStat = std::make_unique<CountAndTime>(oldStat->
count_ - 1, newTime);
649 accumulatedTime += (newTime - oldStat->
time_) * oldStat->
count_;
650 countAndTime.store(newStat.release());
652 countAndTime.store(oldStat);
std::vector< double > sum_events_time_
void setComment(std::string const &value)
#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 preModule(ModuleDescription const &md)
void postEvent(StreamContext const &)
void preModuleStream(StreamContext const &, ModuleCallingContext const &)
std::atomic< unsigned long > begin_lumi_count_
void lastPostEvent(double curr_event_time, unsigned int index, StreamContext const &iStream)
Log< level::Error, false > LogError
void accumulateTimeBegin(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
void preSourceLumi(LuminosityBlockIndex)
std::unique_ptr< T, impl::DeviceDeleter > unique_ptr
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 &)
std::atomic< CountAndTime * > countAndTimeForGet_
void accumulateTimeEnd(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
std::atomic< double > end_loop_time_
Timing(ParameterSet const &, ActivityRegistry &)
CountAndTime(unsigned int count, double time)
ModuleDescription const * moduleDescription() const
void postModuleEvent(StreamContext const &, ModuleCallingContext const &)
#define CMS_THREAD_GUARD(_var_)
Log< level::Error, true > LogImportant
void postSourceLumi(LuminosityBlockIndex)
static void pushStack(bool configuredInTopLevelProcess)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::atomic< double > end_loop_cpu_
std::atomic< CountAndTime * > countAndTimeForLock_
double accumulatedTimeForLock_
Log< level::Warning, true > LogPrint
double getTotalCPU() const override
std::vector< std::unique_ptr< std::atomic< unsigned int > > > countSubProcessesPreEvent_
static double jobStartTime()
std::vector< std::unique_ptr< std::atomic< unsigned int > > > countSubProcessesPostEvent_
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
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
bool configuredInTopLevelProcess_
edm::serviceregistry::AllArgsMaker< edm::TimingServiceBase, Timing > TimingMaker
ProcessContext const * processContext() const
void postSourceRun(RunIndex)
double accumulatedTimeForGet_
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 &)
static double getChildrenCPU()
std::vector< double > min_events_time_
unsigned int nSubProcesses_