CMS 3D CMS Logo

Timing.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Services
4 // Class : Timing
5 //
6 // Implementation:
7 //
8 // Original Author: Jim Kowalkowski
9 //
10 
12 
29 
30 #include <iostream>
31 #include <sstream>
32 #include <sys/resource.h>
33 #include <sys/time.h>
34 #include <atomic>
35 #include <exception>
36 
37 namespace edm {
38 
39  namespace eventsetup {
40  struct ComponentDescription;
41  class DataKey;
42  class EventSetupRecordKey;
43  }
44 
45  namespace service {
46  class Timing : public TimingServiceBase {
47  public:
49  ~Timing() override;
50 
51  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
52 
53  void addToCPUTime(double iTime) override;
54  double getTotalCPU() const override;
55 
56  private:
57 
58  void preBeginJob(PathsAndConsumesOfModulesBase const&, ProcessContext const&);
59  void postBeginJob();
60  void postEndJob();
61 
62  void preEvent(StreamContext const&);
63  void postEvent(StreamContext const&);
64  void lastPostEvent(double curr_event_time, unsigned int index, StreamContext const& iStream);
65 
66  void postModuleEvent(StreamContext const&, ModuleCallingContext const&);
67 
68  void preSourceEvent(StreamID);
69  void postSourceEvent(StreamID);
70 
71  void preSourceLumi(LuminosityBlockIndex);
72  void postSourceLumi(LuminosityBlockIndex);
73 
74  void preSourceRun(RunIndex);
75  void postSourceRun(RunIndex);
76 
77  void preOpenFile(std::string const&, bool);
78  void postOpenFile(std::string const&, bool);
79 
80  void preModule(ModuleDescription const& md);
81  void postModule(ModuleDescription const& md);
82 
83  void preModuleGlobal(GlobalContext const&, ModuleCallingContext const&);
84  void postModuleGlobal(GlobalContext const&, ModuleCallingContext const&);
85 
86  void postGlobalBeginRun(GlobalContext const&);
87  void postGlobalBeginLumi(GlobalContext const&);
88 
89  void preModuleStream(StreamContext const&, ModuleCallingContext const&);
90  void postModuleStream(StreamContext const&, ModuleCallingContext const&);
91 
92  double postCommon() const;
93 
94  void preLockEventSetupGet(eventsetup::ComponentDescription const*,
96  eventsetup::DataKey const&);
97 
98  void postLockEventSetupGet(eventsetup::ComponentDescription const*,
100  eventsetup::DataKey const&);
101 
102  void postEventSetupGet(eventsetup::ComponentDescription const*,
104  eventsetup::DataKey const&);
105 
106  struct CountAndTime {
107  public:
108  CountAndTime(unsigned int count, double time) : count_(count), time_(time) { }
109  unsigned int count_;
110  double time_;
111  };
112 
113  void accumulateTimeBegin(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime);
114  void accumulateTimeEnd(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime);
115 
116  double curr_job_time_; // seconds
117  double curr_job_cpu_; // seconds
118  std::atomic<double> extra_job_cpu_; //seconds
119  //use last run time for determining end of processing
120  std::atomic<double> last_run_time_;
121  std::atomic<double> last_run_cpu_;
122  std::vector<double> curr_events_time_; // seconds
125  double threshold_;
126  //
127  // Min Max and total event times for each Stream.
128  // Used for summary at end of job
129  std::vector<double> max_events_time_; // seconds
130  std::vector<double> min_events_time_; // seconds
131  std::vector<double> sum_events_time_;
132  std::atomic<unsigned long> total_event_count_;
133  std::atomic<unsigned long> begin_lumi_count_;
134  std::atomic<unsigned long> begin_run_count_;
135  unsigned int nStreams_;
136  unsigned int nThreads_;
137 
139 
140  std::atomic<CountAndTime*> countAndTimeForLock_;
141  CMS_THREAD_GUARD(countAndTimeForLock_) double accumulatedTimeForLock_;
142 
143  std::atomic<CountAndTime*> countAndTimeForGet_;
144  CMS_THREAD_GUARD(countAndTimeForGet_) double accumulatedTimeForGet_;
145 
146  std::vector<std::unique_ptr<std::atomic<unsigned int>>> countSubProcessesPreEvent_;
147  std::vector<std::unique_ptr<std::atomic<unsigned int>>> countSubProcessesPostEvent_;
148 
149  bool configuredInTopLevelProcess_;
150  unsigned int nSubProcesses_;
151  };
152  }
153 }
154 
155 namespace edm {
156  namespace service {
157 
158  static std::string d2str(double d) {
159  std::stringstream t;
160  t << d;
161  return t.str();
162  }
163 
164  static std::string ui2str(unsigned int i) {
165  std::stringstream t;
166  t << i;
167  return t.str();
168  }
169 
170 
171  static double getTime() {
172  struct timeval t;
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);
176  }
177 
178  static double getCPU() {
179  struct rusage usage;
180  getrusage(RUSAGE_SELF, &usage);
181 
182  double totalCPUTime = 0.0;
183  // User code
184  totalCPUTime = (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6);
185  // System functions
186  totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6);
187 
188  // Additionally, add in CPU usage from our child processes.
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);
192 
193  return totalCPUTime;
194  }
195 
196  //NOTE: We use a per thread stack for module times since unscheduled
197  // exectuion or tbb task spawning can cause a module to run on the
198  // same thread as an already running module
199  static
200  std::vector<double>& moduleTimeStack() {
201  static thread_local std::vector<double> s_stack;
202  return s_stack;
203  }
204 
205  static
206  double popStack() {
207  auto& modStack = moduleTimeStack();
208  assert(!modStack.empty());
209  double curr_module_time = modStack.back();
210  modStack.pop_back();
211  double t = getTime() - curr_module_time;
212  return t;
213  }
214 
215  static
216  void pushStack(bool configuredInTopLevelProcess) {
217  if (!configuredInTopLevelProcess) {
218  return;
219  }
220  auto& modStack = moduleTimeStack();
221  modStack.push_back(getTime());
222  }
223 
224  Timing::Timing(ParameterSet const& iPS, ActivityRegistry& iRegistry) :
225  curr_job_time_(0.),
226  curr_job_cpu_(0.),
227  extra_job_cpu_(0.0),
228  last_run_time_(0.0),
229  last_run_cpu_(0.0),
230  curr_events_time_(),
231  summary_only_(iPS.getUntrackedParameter<bool>("summaryOnly")),
232  report_summary_(iPS.getUntrackedParameter<bool>("useJobReport")),
233  threshold_(iPS.getUntrackedParameter<double>("excessiveTimeThreshold")),
234  max_events_time_(),
235  min_events_time_(),
236  total_event_count_(0),
237  begin_lumi_count_(0),
238  begin_run_count_(0),
239  countAndTimeZero_{0, 0.0},
240  countAndTimeForLock_{&countAndTimeZero_},
241  accumulatedTimeForLock_{0.0},
242  countAndTimeForGet_{&countAndTimeZero_},
243  accumulatedTimeForGet_{0.0},
244  configuredInTopLevelProcess_{false},
245  nSubProcesses_{0} {
246 
247  iRegistry.watchPreBeginJob(this, &Timing::preBeginJob);
248  iRegistry.watchPostBeginJob(this, &Timing::postBeginJob);
249  iRegistry.watchPostEndJob(this, &Timing::postEndJob);
250 
251  iRegistry.watchPreEvent(this, &Timing::preEvent);
252  iRegistry.watchPostEvent(this, &Timing::postEvent);
253 
254  iRegistry.watchPreLockEventSetupGet(this, &Timing::preLockEventSetupGet);
255  iRegistry.watchPostLockEventSetupGet(this, &Timing::postLockEventSetupGet);
256  iRegistry.watchPostEventSetupGet(this, &Timing::postEventSetupGet);
257 
258  bool checkThreshold = true;
259  if (threshold_ <= 0.0) {
260  //we need to ignore the threshold check
261  threshold_ = std::numeric_limits<double>::max();
262  checkThreshold = false;
263  }
264 
265  if( (not summary_only_) || (checkThreshold) ) {
266  iRegistry.watchPreModuleEvent(this, &Timing::preModuleStream);
267  iRegistry.watchPostModuleEvent(this, &Timing::postModuleEvent);
268  }
269  if(checkThreshold) {
270  iRegistry.watchPreSourceEvent(this, &Timing::preSourceEvent);
271  iRegistry.watchPostSourceEvent(this, &Timing::postSourceEvent);
272 
273  iRegistry.watchPreSourceLumi(this, &Timing::preSourceLumi);
274  iRegistry.watchPostSourceLumi(this, &Timing::postSourceLumi);
275 
276  iRegistry.watchPreSourceRun(this, &Timing::preSourceRun);
277  iRegistry.watchPostSourceRun(this, &Timing::postSourceRun);
278 
279  iRegistry.watchPreOpenFile(this, &Timing::preOpenFile);
280  iRegistry.watchPostOpenFile(this, &Timing::postOpenFile);
281 
282  iRegistry.watchPreEventReadFromSource(this, &Timing::preModuleStream);
283  iRegistry.watchPostEventReadFromSource(this, &Timing::postModuleStream);
284 
285  iRegistry.watchPreModuleConstruction(this, &Timing::preModule);
286  iRegistry.watchPostModuleConstruction(this, &Timing::postModule);
287 
288  iRegistry.watchPreModuleBeginJob(this, &Timing::preModule);
289  iRegistry.watchPostModuleBeginJob(this, &Timing::postModule);
290 
291  iRegistry.watchPreModuleEndJob(this, &Timing::preModule);
292  iRegistry.watchPostModuleEndJob(this, &Timing::postModule);
293 
294  iRegistry.watchPreModuleStreamBeginRun(this, &Timing::preModuleStream);
295  iRegistry.watchPostModuleStreamBeginRun(this, &Timing::postModuleStream);
296  iRegistry.watchPreModuleStreamEndRun(this, &Timing::preModuleStream);
297  iRegistry.watchPostModuleStreamEndRun(this, &Timing::postModuleStream);
298 
299  iRegistry.watchPreModuleStreamBeginLumi(this, &Timing::preModuleStream);
300  iRegistry.watchPostModuleStreamBeginLumi(this, &Timing::postModuleStream);
301  iRegistry.watchPreModuleStreamEndLumi(this, &Timing::preModuleStream);
302  iRegistry.watchPostModuleStreamEndLumi(this, &Timing::postModuleStream);
303 
304  iRegistry.watchPreModuleGlobalBeginRun(this, &Timing::preModuleGlobal);
305  iRegistry.watchPostModuleGlobalBeginRun(this, &Timing::postModuleGlobal);
306  iRegistry.watchPreModuleGlobalEndRun(this, &Timing::preModuleGlobal);
307  iRegistry.watchPostModuleGlobalEndRun(this, &Timing::postModuleGlobal);
308 
309  iRegistry.watchPreModuleGlobalBeginLumi(this, &Timing::preModuleGlobal);
310  iRegistry.watchPostModuleGlobalBeginLumi(this, &Timing::postModuleGlobal);
311  iRegistry.watchPreModuleGlobalEndLumi(this, &Timing::preModuleGlobal);
312  iRegistry.watchPostModuleGlobalEndLumi(this, &Timing::postModuleGlobal);
313 
314  iRegistry.watchPreSourceConstruction(this, &Timing::preModule);
315  iRegistry.watchPostSourceConstruction(this, &Timing::postModule);
316  }
317 
318  iRegistry.watchPostGlobalBeginRun(this, &Timing::postGlobalBeginRun);
319  iRegistry.watchPostGlobalBeginLumi(this, &Timing::postGlobalBeginLumi);
320 
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));
331  }
332  });
333 
334  iRegistry.postGlobalEndRunSignal_.connect([this](edm::GlobalContext const&) {
335  last_run_time_ = getTime();
336  last_run_cpu_ = getCPU();
337  });
338  }
339 
341  }
342 
343  void Timing::addToCPUTime(double iTime) {
344  //For accounting purposes we effectively can say we started earlier
345  double expected = extra_job_cpu_.load();
346  while( not extra_job_cpu_.compare_exchange_strong(expected,expected+iTime) ) {}
347  }
348 
349  double Timing::getTotalCPU() const {
350  return getCPU();
351  }
352 
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");
359  desc.addUntracked<double>("excessiveTimeThreshold", 0.)->setComment(
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);
362  descriptions.setComment(
363  "This service reports the time it takes to run each module in a job.");
364  }
365 
366  void Timing::preBeginJob(PathsAndConsumesOfModulesBase const& pathsAndConsumes, ProcessContext const& pc) {
367  if (pc.isSubProcess()) {
368  ++nSubProcesses_;
369  } else {
370  configuredInTopLevelProcess_ = true;
371  }
372  }
373 
375  if (!configuredInTopLevelProcess_) {
376  return;
377  }
378  curr_job_time_ = getTime();
379  curr_job_cpu_ = getCPU();
380 
381  if(not summary_only_) {
382  LogImportant("TimeReport")
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";
389  }
390  }
391 
393 
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";
398  return;
399  }
400 
401  const double job_end_time =getTime();
402  const double job_end_cpu =getCPU();
403  double total_job_time = job_end_time - jobStartTime();
404 
405  double total_job_cpu = job_end_cpu+extra_job_cpu_;
406 
407  const double total_initialization_time = curr_job_time_ - jobStartTime();
408  const double total_initialization_cpu = curr_job_cpu_;
409 
410  if( 0.0 == jobStartTime()) {
411  //did not capture beginning time
412  total_job_time =job_end_time - curr_job_time_;
413  total_job_cpu =job_end_cpu + extra_job_cpu_ - curr_job_cpu_ ;
414  }
415 
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()));
420 
421  auto total_loop_time = last_run_time_ - curr_job_time_;
422  auto total_loop_cpu = last_run_cpu_ + extra_job_cpu_ - curr_job_cpu_;
423 
424  if(last_run_time_ == 0.0) {
425  total_loop_time = 0.0;
426  total_loop_cpu = 0.0;
427  }
428 
429  double sum_all_events_time = 0;
430  for(auto t : sum_events_time_) { sum_all_events_time += t; }
431 
432  double average_event_time = 0.0;
433  if(total_event_count_ != 0) {
434  average_event_time = sum_all_events_time / total_event_count_;
435  }
436 
437  double event_throughput = 0.0;
438  if(total_loop_time != 0.0) {
439  event_throughput = total_event_count_ / total_loop_time;
440  }
441 
442  LogImportant("TimeReport")
443  << "TimeReport> Time report complete in "
444  << total_job_time << " seconds"
445  << "\n"
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";
465 
466  if(report_summary_) {
467  Service<JobReport> reportSvc;
468  std::map<std::string, std::string> reportData;
469 
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);
485 
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);
491  }
492  }
493 
494  void Timing::preEvent(StreamContext const& iStream) {
495  if (!configuredInTopLevelProcess_) {
496  return;
497  }
498  auto index = iStream.streamID().value();
499  if (nSubProcesses_ == 0u) {
500  curr_events_time_[index] = getTime();
501  } else {
502  unsigned int count = ++(*countSubProcessesPreEvent_[index]);
503  if (count == 1) {
504  curr_events_time_[index] = getTime();
505  } else if (count == (nSubProcesses_ + 1)) {
506  *countSubProcessesPreEvent_[index] = 0;
507  }
508  }
509  }
510 
511  void Timing::postEvent(StreamContext const& iStream) {
512  if (!configuredInTopLevelProcess_) {
513  return;
514  }
515  auto index = iStream.streamID().value();
516  if (nSubProcesses_ == 0u) {
517  lastPostEvent(getTime() - curr_events_time_[index], index, iStream);
518  } else {
519  unsigned int count = ++(*countSubProcessesPostEvent_[index]);
520  if (count == (nSubProcesses_ + 1)) {
521  lastPostEvent(getTime() - curr_events_time_[index], index, iStream);
522  *countSubProcessesPostEvent_[index] = 0;
523  }
524  }
525  }
526 
527  void Timing::lastPostEvent(double curr_event_time, unsigned int index, StreamContext const& iStream) {
528  sum_events_time_[index] +=curr_event_time;
529 
530  if(not summary_only_) {
531  auto const & eventID = iStream.eventID();
532  LogPrint("TimeEvent")
533  << "TimeEvent> "
534  << eventID.event() << " "
535  << eventID.run() << " "
536  << curr_event_time ;
537  }
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;
541  }
542 
543  void Timing::postModuleEvent(StreamContext const& iStream, ModuleCallingContext const& iModule) {
544  if (!configuredInTopLevelProcess_) {
545  return;
546  }
547  auto const & eventID = iStream.eventID();
548  auto const & desc = *(iModule.moduleDescription());
549  double t = postCommon();
550  if ( not summary_only_) {
551  LogPrint("TimeModule") << "TimeModule> "
552  << eventID.event() << " "
553  << eventID.run() << " "
554  << desc.moduleLabel() << " "
555  << desc.moduleName() << " "
556  << t;
557  }
558  }
559 
561  pushStack(configuredInTopLevelProcess_);
562  }
563 
565  postCommon();
566  }
567 
569  pushStack(configuredInTopLevelProcess_);
570  }
571 
573  postCommon();
574  }
575 
577  pushStack(configuredInTopLevelProcess_);
578  }
579 
581  postCommon();
582  }
583 
584  void Timing::preOpenFile(std::string const& lfn, bool b) {
585  pushStack(configuredInTopLevelProcess_);
586  }
587 
588  void Timing::postOpenFile(std::string const& lfn, bool b) {
589  postCommon();
590  }
591 
592  void
594  pushStack(configuredInTopLevelProcess_);
595  }
596 
597  void
599  postCommon();
600  }
601 
602  void
604  pushStack(configuredInTopLevelProcess_);
605  }
606 
607  void
609  postCommon();
610  }
611 
612  void
614  if (!configuredInTopLevelProcess_) {
615  return;
616  }
617  if (!gc.processContext()->isSubProcess()) {
619  }
620  }
621 
622  void
624  if (!configuredInTopLevelProcess_) {
625  return;
626  }
627  if (!gc.processContext()->isSubProcess()) {
629  }
630  }
631 
632  void
634  pushStack(configuredInTopLevelProcess_);
635  }
636 
637  void
639  postCommon();
640  }
641 
642  double
644  if (!configuredInTopLevelProcess_) {
645  return 0.0;
646  }
647  double t = popStack();
648  if(t > threshold_) {
649  LogError("ExcessiveTime")
650  << "ExcessiveTime: Module used " << t
651  << " seconds of time which exceeds the error threshold configured in the Timing Service of "
652  << threshold_ << " seconds.";
653  }
654  return t;
655  }
656 
657  void
660  eventsetup::DataKey const&) {
661 
662  if (!configuredInTopLevelProcess_) {
663  return;
664  }
665  accumulateTimeBegin(countAndTimeForLock_, accumulatedTimeForLock_);
666  }
667 
668  void
671  eventsetup::DataKey const&) {
672 
673  if (!configuredInTopLevelProcess_) {
674  return;
675  }
676  accumulateTimeEnd(countAndTimeForLock_, accumulatedTimeForLock_);
677  accumulateTimeBegin(countAndTimeForGet_, accumulatedTimeForGet_);
678  }
679 
680  void
683  eventsetup::DataKey const&) {
684 
685  accumulateTimeEnd(countAndTimeForGet_, accumulatedTimeForGet_);
686  }
687 
688  void
689  Timing::accumulateTimeBegin(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime) {
690 
691  double newTime = getTime();
692  auto newStat = std::make_unique<CountAndTime>(0, newTime);
693 
694  CountAndTime* oldStat = countAndTime.load();
695  while (true) {
696  if (oldStat == nullptr) {
697  oldStat = countAndTime.load();
698  } else if (countAndTime.compare_exchange_strong(oldStat, nullptr)) {
699  break;
700  }
701  }
702 
703  newStat->count_ = oldStat->count_ + 1;
704  if (oldStat->count_ != 0) {
705  accumulatedTime += (newTime - oldStat->time_) * oldStat->count_;
706  }
707  countAndTime.store(newStat.release());
708  if (oldStat != &countAndTimeZero_) {
709  delete oldStat;
710  }
711  }
712 
713  void
714  Timing::accumulateTimeEnd(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime) {
715 
716  double newTime = getTime();
717 
718  CountAndTime* oldStat = countAndTime.load();
719  while (true) {
720  if (oldStat == nullptr) {
721  oldStat = countAndTime.load();
722  } else if (countAndTime.compare_exchange_strong(oldStat, nullptr)) {
723  break;
724  }
725  }
726 
727  if (oldStat->count_ == 1) {
728  accumulatedTime += newTime - oldStat->time_;
729  countAndTime.store(&countAndTimeZero_);
730  } else {
731  try {
732  auto newStat = std::make_unique<CountAndTime>(oldStat->count_ - 1, newTime);
733  accumulatedTime += (newTime - oldStat->time_) * oldStat->count_;
734  countAndTime.store(newStat.release());
735  } catch (std::exception &) {
736  countAndTime.store(oldStat);
737  throw;
738  }
739  }
740  delete oldStat;
741  }
742  }
743 }
744 
746 
std::vector< double > sum_events_time_
Definition: Timing.cc:131
void setComment(std::string const &value)
double curr_job_time_
Definition: Timing.cc:116
std::atomic< double > last_run_cpu_
Definition: Timing.cc:121
#define DEFINE_FWK_SERVICE_MAKER(concrete, maker)
Definition: ServiceMaker.h:117
std::vector< double > max_events_time_
Definition: Timing.cc:129
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
std::vector< double > curr_events_time_
Definition: Timing.cc:122
void postLockEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
Definition: Timing.cc:669
double getTotalCPU() const override
Definition: Timing.cc:349
void preModule(ModuleDescription const &md)
Definition: Timing.cc:593
static double getCPU()
Definition: Timing.cc:178
void postEvent(StreamContext const &)
Definition: Timing.cc:511
void preModuleStream(StreamContext const &, ModuleCallingContext const &)
Definition: Timing.cc:633
double curr_job_cpu_
Definition: Timing.cc:117
std::atomic< unsigned long > begin_lumi_count_
Definition: Timing.cc:133
edm::serviceregistry::AllArgsMaker< edm::TimingServiceBase, Timing > TimingMaker
Definition: Timing.cc:747
void lastPostEvent(double curr_event_time, unsigned int index, StreamContext const &iStream)
Definition: Timing.cc:527
void accumulateTimeBegin(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
Definition: Timing.cc:689
void preSourceLumi(LuminosityBlockIndex)
Definition: Timing.cc:568
unsigned int nThreads_
Definition: Timing.cc:136
void preOpenFile(std::string const &, bool)
Definition: Timing.cc:584
unsigned int nStreams_
Definition: Timing.cc:135
void preModuleGlobal(GlobalContext const &, ModuleCallingContext const &)
Definition: Timing.cc:603
void postModule(ModuleDescription const &md)
Definition: Timing.cc:598
void postGlobalBeginRun(GlobalContext const &)
Definition: Timing.cc:613
void preSourceRun(RunIndex)
Definition: Timing.cc:576
void postModuleStream(StreamContext const &, ModuleCallingContext const &)
Definition: Timing.cc:638
void accumulateTimeEnd(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
Definition: Timing.cc:714
CountAndTime(unsigned int count, double time)
Definition: Timing.cc:108
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
ModuleDescription const * moduleDescription() const
void postModuleEvent(StreamContext const &, ModuleCallingContext const &)
Definition: Timing.cc:543
#define CMS_THREAD_GUARD(_var_)
std::atomic< double > last_run_time_
Definition: Timing.cc:120
void postSourceLumi(LuminosityBlockIndex)
Definition: Timing.cc:572
static void pushStack(bool configuredInTopLevelProcess)
Definition: Timing.cc:216
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: Timing.cc:353
~Timing() override
Definition: Timing.cc:340
std::atomic< CountAndTime * > countAndTimeForLock_
Definition: Timing.cc:140
void preLockEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
Definition: Timing.cc:658
static double jobStartTime()
StreamID const & streamID() const
Definition: StreamContext.h:57
static std::string ui2str(unsigned int i)
Definition: Timing.cc:164
void setComment(std::string const &value)
void postGlobalBeginLumi(GlobalContext const &)
Definition: Timing.cc:623
std::atomic< unsigned long > begin_run_count_
Definition: Timing.cc:134
unsigned int value() const
Definition: StreamID.h:46
void postEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
Definition: Timing.cc:681
std::atomic< unsigned long > total_event_count_
Definition: Timing.cc:132
static std::vector< double > & moduleTimeStack()
Definition: Timing.cc:200
void addToCPUTime(double iTime) override
Definition: Timing.cc:343
double b
Definition: hdecay.h:120
static std::string d2str(double d)
Definition: Timing.cc:158
void add(std::string const &label, ParameterSetDescription const &psetDescription)
double postCommon() const
Definition: Timing.cc:643
ProcessContext const * processContext() const
Definition: GlobalContext.h:61
void postSourceRun(RunIndex)
Definition: Timing.cc:580
void postModuleGlobal(GlobalContext const &, ModuleCallingContext const &)
Definition: Timing.cc:608
void preBeginJob(PathsAndConsumesOfModulesBase const &, ProcessContext const &)
Definition: Timing.cc:366
HLT enums.
CountAndTime countAndTimeZero_
Definition: Timing.cc:138
void postOpenFile(std::string const &, bool)
Definition: Timing.cc:588
static double getTime()
Definition: Timing.cc:171
void postSourceEvent(StreamID)
Definition: Timing.cc:564
EventID const & eventID() const
Definition: StreamContext.h:63
std::atomic< double > extra_job_cpu_
Definition: Timing.cc:118
static double popStack()
Definition: Timing.cc:206
bool isSubProcess() const
void preSourceEvent(StreamID)
Definition: Timing.cc:560
void preEvent(StreamContext const &)
Definition: Timing.cc:494
std::vector< double > min_events_time_
Definition: Timing.cc:130
unsigned int nSubProcesses_
Definition: Timing.cc:150