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  } // namespace eventsetup
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  void preBeginJob(PathsAndConsumesOfModulesBase const&, ProcessContext const&);
58  void postBeginJob();
59  void postEndJob();
60 
61  void preEvent(StreamContext const&);
62  void postEvent(StreamContext const&);
63  void lastPostEvent(double curr_event_time, unsigned int index, StreamContext const& iStream);
64 
65  void postModuleEvent(StreamContext const&, ModuleCallingContext const&);
66 
67  void preSourceEvent(StreamID);
68  void postSourceEvent(StreamID);
69 
70  void preSourceLumi(LuminosityBlockIndex);
71  void postSourceLumi(LuminosityBlockIndex);
72 
73  void preSourceRun(RunIndex);
74  void postSourceRun(RunIndex);
75 
76  void preOpenFile(std::string const&, bool);
77  void postOpenFile(std::string const&, bool);
78 
79  void preModule(ModuleDescription const& md);
80  void postModule(ModuleDescription const& md);
81 
82  void preModuleGlobal(GlobalContext const&, ModuleCallingContext const&);
83  void postModuleGlobal(GlobalContext const&, ModuleCallingContext const&);
84 
85  void postGlobalBeginRun(GlobalContext const&);
86  void postGlobalBeginLumi(GlobalContext const&);
87 
88  void preModuleStream(StreamContext const&, ModuleCallingContext const&);
89  void postModuleStream(StreamContext const&, ModuleCallingContext const&);
90 
91  double postCommon() const;
92 
93  void preLockEventSetupGet(eventsetup::ComponentDescription const*,
95  eventsetup::DataKey const&);
96 
97  void postLockEventSetupGet(eventsetup::ComponentDescription const*,
99  eventsetup::DataKey const&);
100 
101  void postEventSetupGet(eventsetup::ComponentDescription const*,
103  eventsetup::DataKey const&);
104 
105  struct CountAndTime {
106  public:
107  CountAndTime(unsigned int count, double time) : count_(count), time_(time) {}
108  unsigned int count_;
109  double time_;
110  };
111 
112  void accumulateTimeBegin(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime);
113  void accumulateTimeEnd(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime);
114 
115  double curr_job_time_; // seconds
116  double curr_job_cpu_; // seconds
117  std::atomic<double> extra_job_cpu_; //seconds
118  //use last run time for determining end of processing
119  std::atomic<double> last_run_time_;
120  std::atomic<double> last_run_cpu_;
121  std::vector<double> curr_events_time_; // seconds
124  double threshold_;
125  //
126  // Min Max and total event times for each Stream.
127  // Used for summary at end of job
128  std::vector<double> max_events_time_; // seconds
129  std::vector<double> min_events_time_; // seconds
130  std::vector<double> sum_events_time_;
131  std::atomic<unsigned long> total_event_count_;
132  std::atomic<unsigned long> begin_lumi_count_;
133  std::atomic<unsigned long> begin_run_count_;
134  unsigned int nStreams_;
135  unsigned int nThreads_;
136 
138 
139  std::atomic<CountAndTime*> countAndTimeForLock_;
140  CMS_THREAD_GUARD(countAndTimeForLock_) double accumulatedTimeForLock_;
141 
142  std::atomic<CountAndTime*> countAndTimeForGet_;
143  CMS_THREAD_GUARD(countAndTimeForGet_) double accumulatedTimeForGet_;
144 
145  std::vector<std::unique_ptr<std::atomic<unsigned int>>> countSubProcessesPreEvent_;
146  std::vector<std::unique_ptr<std::atomic<unsigned int>>> countSubProcessesPostEvent_;
147 
148  bool configuredInTopLevelProcess_;
149  unsigned int nSubProcesses_;
150  };
151  } // namespace service
152 } // namespace edm
153 
154 namespace edm {
155  namespace service {
156 
157  static std::string d2str(double d) {
158  std::stringstream t;
159  t << d;
160  return t.str();
161  }
162 
163  static std::string ui2str(unsigned int i) {
164  std::stringstream t;
165  t << i;
166  return t.str();
167  }
168 
169  static double getTime() {
170  struct timeval t;
171  if (gettimeofday(&t, nullptr) < 0)
172  throw cms::Exception("SysCallFailed", "Failed call to gettimeofday");
173  return static_cast<double>(t.tv_sec) + (static_cast<double>(t.tv_usec) * 1E-6);
174  }
175 
176  static double getCPU() {
177  struct rusage usage;
178  getrusage(RUSAGE_SELF, &usage);
179 
180  double totalCPUTime = 0.0;
181  // User code
182  totalCPUTime = (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6);
183  // System functions
184  totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6);
185 
186  // Additionally, add in CPU usage from our child processes.
187  getrusage(RUSAGE_CHILDREN, &usage);
188  totalCPUTime += (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6);
189  totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6);
190 
191  return totalCPUTime;
192  }
193 
194  //NOTE: We use a per thread stack for module times since unscheduled
195  // exectuion or tbb task spawning can cause a module to run on the
196  // same thread as an already running module
197  static std::vector<double>& moduleTimeStack() {
198  static thread_local std::vector<double> s_stack;
199  return s_stack;
200  }
201 
202  static double popStack() {
203  auto& modStack = moduleTimeStack();
204  assert(!modStack.empty());
205  double curr_module_time = modStack.back();
206  modStack.pop_back();
207  double t = getTime() - curr_module_time;
208  return t;
209  }
210 
211  static void pushStack(bool configuredInTopLevelProcess) {
212  if (!configuredInTopLevelProcess) {
213  return;
214  }
215  auto& modStack = moduleTimeStack();
216  modStack.push_back(getTime());
217  }
218 
220  : curr_job_time_(0.),
221  curr_job_cpu_(0.),
222  extra_job_cpu_(0.0),
223  last_run_time_(0.0),
224  last_run_cpu_(0.0),
225  curr_events_time_(),
226  summary_only_(iPS.getUntrackedParameter<bool>("summaryOnly")),
227  report_summary_(iPS.getUntrackedParameter<bool>("useJobReport")),
228  threshold_(iPS.getUntrackedParameter<double>("excessiveTimeThreshold")),
229  max_events_time_(),
230  min_events_time_(),
231  total_event_count_(0),
232  begin_lumi_count_(0),
233  begin_run_count_(0),
234  countAndTimeZero_{0, 0.0},
235  countAndTimeForLock_{&countAndTimeZero_},
236  accumulatedTimeForLock_{0.0},
237  countAndTimeForGet_{&countAndTimeZero_},
238  accumulatedTimeForGet_{0.0},
239  configuredInTopLevelProcess_{false},
240  nSubProcesses_{0} {
241  iRegistry.watchPreBeginJob(this, &Timing::preBeginJob);
242  iRegistry.watchPostBeginJob(this, &Timing::postBeginJob);
243  iRegistry.watchPostEndJob(this, &Timing::postEndJob);
244 
245  iRegistry.watchPreEvent(this, &Timing::preEvent);
246  iRegistry.watchPostEvent(this, &Timing::postEvent);
247 
248  iRegistry.watchPreLockEventSetupGet(this, &Timing::preLockEventSetupGet);
249  iRegistry.watchPostLockEventSetupGet(this, &Timing::postLockEventSetupGet);
250  iRegistry.watchPostEventSetupGet(this, &Timing::postEventSetupGet);
251 
252  bool checkThreshold = true;
253  if (threshold_ <= 0.0) {
254  //we need to ignore the threshold check
255  threshold_ = std::numeric_limits<double>::max();
256  checkThreshold = false;
257  }
258 
259  if ((not summary_only_) || (checkThreshold)) {
260  iRegistry.watchPreModuleEvent(this, &Timing::preModuleStream);
261  iRegistry.watchPostModuleEvent(this, &Timing::postModuleEvent);
262  }
263  if (checkThreshold) {
264  iRegistry.watchPreSourceEvent(this, &Timing::preSourceEvent);
265  iRegistry.watchPostSourceEvent(this, &Timing::postSourceEvent);
266 
267  iRegistry.watchPreSourceLumi(this, &Timing::preSourceLumi);
268  iRegistry.watchPostSourceLumi(this, &Timing::postSourceLumi);
269 
270  iRegistry.watchPreSourceRun(this, &Timing::preSourceRun);
271  iRegistry.watchPostSourceRun(this, &Timing::postSourceRun);
272 
273  iRegistry.watchPreOpenFile(this, &Timing::preOpenFile);
274  iRegistry.watchPostOpenFile(this, &Timing::postOpenFile);
275 
276  iRegistry.watchPreEventReadFromSource(this, &Timing::preModuleStream);
277  iRegistry.watchPostEventReadFromSource(this, &Timing::postModuleStream);
278 
279  iRegistry.watchPreModuleConstruction(this, &Timing::preModule);
280  iRegistry.watchPostModuleConstruction(this, &Timing::postModule);
281 
282  iRegistry.watchPreModuleBeginJob(this, &Timing::preModule);
283  iRegistry.watchPostModuleBeginJob(this, &Timing::postModule);
284 
285  iRegistry.watchPreModuleEndJob(this, &Timing::preModule);
286  iRegistry.watchPostModuleEndJob(this, &Timing::postModule);
287 
288  iRegistry.watchPreModuleStreamBeginRun(this, &Timing::preModuleStream);
289  iRegistry.watchPostModuleStreamBeginRun(this, &Timing::postModuleStream);
290  iRegistry.watchPreModuleStreamEndRun(this, &Timing::preModuleStream);
291  iRegistry.watchPostModuleStreamEndRun(this, &Timing::postModuleStream);
292 
293  iRegistry.watchPreModuleStreamBeginLumi(this, &Timing::preModuleStream);
294  iRegistry.watchPostModuleStreamBeginLumi(this, &Timing::postModuleStream);
295  iRegistry.watchPreModuleStreamEndLumi(this, &Timing::preModuleStream);
296  iRegistry.watchPostModuleStreamEndLumi(this, &Timing::postModuleStream);
297 
298  iRegistry.watchPreModuleGlobalBeginRun(this, &Timing::preModuleGlobal);
299  iRegistry.watchPostModuleGlobalBeginRun(this, &Timing::postModuleGlobal);
300  iRegistry.watchPreModuleGlobalEndRun(this, &Timing::preModuleGlobal);
301  iRegistry.watchPostModuleGlobalEndRun(this, &Timing::postModuleGlobal);
302 
303  iRegistry.watchPreModuleGlobalBeginLumi(this, &Timing::preModuleGlobal);
304  iRegistry.watchPostModuleGlobalBeginLumi(this, &Timing::postModuleGlobal);
305  iRegistry.watchPreModuleGlobalEndLumi(this, &Timing::preModuleGlobal);
306  iRegistry.watchPostModuleGlobalEndLumi(this, &Timing::postModuleGlobal);
307 
308  iRegistry.watchPreSourceConstruction(this, &Timing::preModule);
309  iRegistry.watchPostSourceConstruction(this, &Timing::postModule);
310  }
311 
312  iRegistry.watchPostGlobalBeginRun(this, &Timing::postGlobalBeginRun);
313  iRegistry.watchPostGlobalBeginLumi(this, &Timing::postGlobalBeginLumi);
314 
315  iRegistry.preallocateSignal_.connect([this](service::SystemBounds const& iBounds) {
316  nStreams_ = iBounds.maxNumberOfStreams();
317  nThreads_ = iBounds.maxNumberOfThreads();
318  curr_events_time_.resize(nStreams_, 0.);
319  sum_events_time_.resize(nStreams_, 0.);
320  max_events_time_.resize(nStreams_, 0.);
321  min_events_time_.resize(nStreams_, 1.E6);
322  for (unsigned int i = 0; i < nStreams_; ++i) {
323  countSubProcessesPreEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
324  countSubProcessesPostEvent_.emplace_back(std::make_unique<std::atomic<unsigned int>>(0));
325  }
326  });
327 
328  iRegistry.postGlobalEndRunSignal_.connect([this](edm::GlobalContext const&) {
329  last_run_time_ = getTime();
330  last_run_cpu_ = getCPU();
331  });
332  }
333 
335 
336  void Timing::addToCPUTime(double iTime) {
337  //For accounting purposes we effectively can say we started earlier
338  double expected = extra_job_cpu_.load();
339  while (not extra_job_cpu_.compare_exchange_strong(expected, expected + iTime)) {
340  }
341  }
342 
343  double Timing::getTotalCPU() const { return getCPU(); }
344 
347  desc.addUntracked<bool>("summaryOnly", false)->setComment("If 'true' do not report timing for each event");
348  desc.addUntracked<bool>("useJobReport", true)->setComment("If 'true' write summary information to JobReport");
349  desc.addUntracked<double>("excessiveTimeThreshold", 0.)
350  ->setComment(
351  "Amount of time in seconds before reporting a module or source has taken excessive time. A value of 0.0 "
352  "turns off this reporting.");
353  descriptions.add("Timing", desc);
354  descriptions.setComment("This service reports the time it takes to run each module in a job.");
355  }
356 
357  void Timing::preBeginJob(PathsAndConsumesOfModulesBase const& pathsAndConsumes, ProcessContext const& pc) {
358  if (pc.isSubProcess()) {
359  ++nSubProcesses_;
360  } else {
361  configuredInTopLevelProcess_ = true;
362  }
363  }
364 
366  if (!configuredInTopLevelProcess_) {
367  return;
368  }
369  curr_job_time_ = getTime();
370  curr_job_cpu_ = getCPU();
371 
372  if (not summary_only_) {
373  LogImportant("TimeReport") << "TimeReport> Report activated"
374  << "\n"
375  << "TimeReport> Report columns headings for events: "
376  << "eventnum runnum timetaken\n"
377  << "TimeReport> Report columns headings for modules: "
378  << "eventnum runnum modulelabel modulename timetakeni\n"
379  << "TimeReport> JobTime=" << curr_job_time_ << " JobCPU=" << curr_job_cpu_ << "\n";
380  }
381  }
382 
384  if (!configuredInTopLevelProcess_) {
385  LogImportant("TimeReport") << "\nTimeReport> This instance of the Timing Service will be disabled because it "
386  "is configured in a SubProcess.\n"
387  << "If multiple instances of the TimingService were configured only the one in the "
388  "top level process will function.\n"
389  << "The other instance(s) will simply print this message and do nothing.\n\n";
390  return;
391  }
392 
393  const double job_end_time = getTime();
394  const double job_end_cpu = getCPU();
395  double total_job_time = job_end_time - jobStartTime();
396 
397  double total_job_cpu = job_end_cpu + extra_job_cpu_;
398 
399  const double total_initialization_time = curr_job_time_ - jobStartTime();
400  const double total_initialization_cpu = curr_job_cpu_;
401 
402  if (0.0 == jobStartTime()) {
403  //did not capture beginning time
404  total_job_time = job_end_time - curr_job_time_;
405  total_job_cpu = job_end_cpu + extra_job_cpu_ - curr_job_cpu_;
406  }
407 
408  double min_event_time = *(std::min_element(min_events_time_.begin(), min_events_time_.end()));
409  double max_event_time = *(std::max_element(max_events_time_.begin(), max_events_time_.end()));
410 
411  auto total_loop_time = last_run_time_ - curr_job_time_;
412  auto total_loop_cpu = last_run_cpu_ + extra_job_cpu_ - curr_job_cpu_;
413 
414  if (last_run_time_ == 0.0) {
415  total_loop_time = 0.0;
416  total_loop_cpu = 0.0;
417  }
418 
419  double sum_all_events_time = 0;
420  for (auto t : sum_events_time_) {
421  sum_all_events_time += t;
422  }
423 
424  double average_event_time = 0.0;
425  if (total_event_count_ != 0) {
426  average_event_time = sum_all_events_time / total_event_count_;
427  }
428 
429  double event_throughput = 0.0;
430  if (total_loop_time != 0.0) {
431  event_throughput = total_event_count_ / total_loop_time;
432  }
433 
434  LogImportant("TimeReport") << "TimeReport> Time report complete in " << total_job_time << " seconds"
435  << "\n"
436  << " Time Summary: \n"
437  << " - Min event: " << min_event_time << "\n"
438  << " - Max event: " << max_event_time << "\n"
439  << " - Avg event: " << average_event_time << "\n"
440  << " - Total loop: " << total_loop_time << "\n"
441  << " - Total init: " << total_initialization_time << "\n"
442  << " - Total job: " << total_job_time << "\n"
443  << " - EventSetup Lock: " << accumulatedTimeForLock_ << "\n"
444  << " - EventSetup Get: " << accumulatedTimeForGet_ << "\n"
445  << " Event Throughput: " << event_throughput << " ev/s\n"
446  << " CPU Summary: \n"
447  << " - Total loop: " << total_loop_cpu << "\n"
448  << " - Total init: " << total_initialization_cpu << "\n"
449  << " - Total extra: " << extra_job_cpu_ << "\n"
450  << " - Total job: " << total_job_cpu << "\n"
451  << " Processing Summary: \n"
452  << " - Number of Events: " << total_event_count_ << "\n"
453  << " - Number of Global Begin Lumi Calls: " << begin_lumi_count_ << "\n"
454  << " - Number of Global Begin Run Calls: " << begin_run_count_ << "\n";
455 
456  if (report_summary_) {
457  Service<JobReport> reportSvc;
458  std::map<std::string, std::string> reportData;
459 
460  reportData.insert(std::make_pair("MinEventTime", d2str(min_event_time)));
461  reportData.insert(std::make_pair("MaxEventTime", d2str(max_event_time)));
462  reportData.insert(std::make_pair("AvgEventTime", d2str(average_event_time)));
463  reportData.insert(std::make_pair("EventThroughput", d2str(event_throughput)));
464  reportData.insert(std::make_pair("TotalJobTime", d2str(total_job_time)));
465  reportData.insert(std::make_pair("TotalJobCPU", d2str(total_job_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);
475 
476  std::map<std::string, std::string> reportData1;
477  reportData1.insert(std::make_pair("NumberEvents", ui2str(total_event_count_)));
478  reportData1.insert(std::make_pair("NumberBeginLumiCalls", ui2str(begin_lumi_count_)));
479  reportData1.insert(std::make_pair("NumberBeginRunCalls", ui2str(begin_run_count_)));
480  reportSvc->reportPerformanceSummary("ProcessingSummary", reportData1);
481  }
482  }
483 
484  void Timing::preEvent(StreamContext const& iStream) {
485  if (!configuredInTopLevelProcess_) {
486  return;
487  }
488  auto index = iStream.streamID().value();
489  if (nSubProcesses_ == 0u) {
490  curr_events_time_[index] = getTime();
491  } else {
492  unsigned int count = ++(*countSubProcessesPreEvent_[index]);
493  if (count == 1) {
494  curr_events_time_[index] = getTime();
495  } else if (count == (nSubProcesses_ + 1)) {
496  *countSubProcessesPreEvent_[index] = 0;
497  }
498  }
499  }
500 
501  void Timing::postEvent(StreamContext const& iStream) {
502  if (!configuredInTopLevelProcess_) {
503  return;
504  }
505  auto index = iStream.streamID().value();
506  if (nSubProcesses_ == 0u) {
507  lastPostEvent(getTime() - curr_events_time_[index], index, iStream);
508  } else {
509  unsigned int count = ++(*countSubProcessesPostEvent_[index]);
510  if (count == (nSubProcesses_ + 1)) {
511  lastPostEvent(getTime() - curr_events_time_[index], index, iStream);
512  *countSubProcessesPostEvent_[index] = 0;
513  }
514  }
515  }
516 
517  void Timing::lastPostEvent(double curr_event_time, unsigned int index, StreamContext const& iStream) {
518  sum_events_time_[index] += curr_event_time;
519 
520  if (not summary_only_) {
521  auto const& eventID = iStream.eventID();
522  LogPrint("TimeEvent") << "TimeEvent> " << eventID.event() << " " << eventID.run() << " " << curr_event_time;
523  }
524  if (curr_event_time > max_events_time_[index])
525  max_events_time_[index] = curr_event_time;
526  if (curr_event_time < min_events_time_[index])
527  min_events_time_[index] = curr_event_time;
529  }
530 
531  void Timing::postModuleEvent(StreamContext const& iStream, ModuleCallingContext const& iModule) {
532  if (!configuredInTopLevelProcess_) {
533  return;
534  }
535  auto const& eventID = iStream.eventID();
536  auto const& desc = *(iModule.moduleDescription());
537  double t = postCommon();
538  if (not summary_only_) {
539  LogPrint("TimeModule") << "TimeModule> " << eventID.event() << " " << eventID.run() << " " << desc.moduleLabel()
540  << " " << desc.moduleName() << " " << t;
541  }
542  }
543 
544  void Timing::preSourceEvent(StreamID sid) { pushStack(configuredInTopLevelProcess_); }
545 
547 
548  void Timing::preSourceLumi(LuminosityBlockIndex index) { pushStack(configuredInTopLevelProcess_); }
549 
551 
552  void Timing::preSourceRun(RunIndex index) { pushStack(configuredInTopLevelProcess_); }
553 
555 
556  void Timing::preOpenFile(std::string const& lfn, bool b) { pushStack(configuredInTopLevelProcess_); }
557 
558  void Timing::postOpenFile(std::string const& lfn, bool b) { postCommon(); }
559 
560  void Timing::preModule(ModuleDescription const&) { pushStack(configuredInTopLevelProcess_); }
561 
563 
565  pushStack(configuredInTopLevelProcess_);
566  }
567 
569 
571  if (!configuredInTopLevelProcess_) {
572  return;
573  }
574  if (!gc.processContext()->isSubProcess()) {
576  }
577  }
578 
580  if (!configuredInTopLevelProcess_) {
581  return;
582  }
583  if (!gc.processContext()->isSubProcess()) {
585  }
586  }
587 
589  pushStack(configuredInTopLevelProcess_);
590  }
591 
593 
594  double Timing::postCommon() const {
595  if (!configuredInTopLevelProcess_) {
596  return 0.0;
597  }
598  double t = popStack();
599  if (t > threshold_) {
600  LogError("ExcessiveTime")
601  << "ExcessiveTime: Module used " << t
602  << " seconds of time which exceeds the error threshold configured in the Timing Service of " << threshold_
603  << " seconds.";
604  }
605  return t;
606  }
607 
610  eventsetup::DataKey const&) {
611  if (!configuredInTopLevelProcess_) {
612  return;
613  }
614  accumulateTimeBegin(countAndTimeForLock_, accumulatedTimeForLock_);
615  }
616 
619  eventsetup::DataKey const&) {
620  if (!configuredInTopLevelProcess_) {
621  return;
622  }
623  accumulateTimeEnd(countAndTimeForLock_, accumulatedTimeForLock_);
624  accumulateTimeBegin(countAndTimeForGet_, accumulatedTimeForGet_);
625  }
626 
629  eventsetup::DataKey const&) {
630  accumulateTimeEnd(countAndTimeForGet_, accumulatedTimeForGet_);
631  }
632 
633  void Timing::accumulateTimeBegin(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime) {
634  double newTime = getTime();
635  auto newStat = std::make_unique<CountAndTime>(0, newTime);
636 
637  CountAndTime* oldStat = countAndTime.load();
638  while (true) {
639  if (oldStat == nullptr) {
640  oldStat = countAndTime.load();
641  } else if (countAndTime.compare_exchange_strong(oldStat, nullptr)) {
642  break;
643  }
644  }
645 
646  newStat->count_ = oldStat->count_ + 1;
647  if (oldStat->count_ != 0) {
648  accumulatedTime += (newTime - oldStat->time_) * oldStat->count_;
649  }
650  countAndTime.store(newStat.release());
651  if (oldStat != &countAndTimeZero_) {
652  delete oldStat;
653  }
654  }
655 
656  void Timing::accumulateTimeEnd(std::atomic<CountAndTime*>& countAndTime, double& accumulatedTime) {
657  double newTime = getTime();
658 
659  CountAndTime* oldStat = countAndTime.load();
660  while (true) {
661  if (oldStat == nullptr) {
662  oldStat = countAndTime.load();
663  } else if (countAndTime.compare_exchange_strong(oldStat, nullptr)) {
664  break;
665  }
666  }
667 
668  if (oldStat->count_ == 1) {
669  accumulatedTime += newTime - oldStat->time_;
670  countAndTime.store(&countAndTimeZero_);
671  } else {
672  try {
673  auto newStat = std::make_unique<CountAndTime>(oldStat->count_ - 1, newTime);
674  accumulatedTime += (newTime - oldStat->time_) * oldStat->count_;
675  countAndTime.store(newStat.release());
676  } catch (std::exception&) {
677  countAndTime.store(oldStat);
678  throw;
679  }
680  }
681  delete oldStat;
682  }
683  } // namespace service
684 } // namespace edm
685 
687 
std::vector< double > sum_events_time_
Definition: Timing.cc:130
void setComment(std::string const &value)
double curr_job_time_
Definition: Timing.cc:115
std::atomic< double > last_run_cpu_
Definition: Timing.cc:120
std::vector< double > max_events_time_
Definition: Timing.cc:128
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
std::vector< double > curr_events_time_
Definition: Timing.cc:121
void postLockEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
Definition: Timing.cc:617
double getTotalCPU() const override
Definition: Timing.cc:343
void preModule(ModuleDescription const &md)
Definition: Timing.cc:560
#define DEFINE_FWK_SERVICE_MAKER(concrete, maker)
Definition: ServiceMaker.h:109
static double getCPU()
Definition: Timing.cc:176
void postEvent(StreamContext const &)
Definition: Timing.cc:501
void preModuleStream(StreamContext const &, ModuleCallingContext const &)
Definition: Timing.cc:588
double curr_job_cpu_
Definition: Timing.cc:116
std::atomic< unsigned long > begin_lumi_count_
Definition: Timing.cc:132
void lastPostEvent(double curr_event_time, unsigned int index, StreamContext const &iStream)
Definition: Timing.cc:517
void accumulateTimeBegin(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
Definition: Timing.cc:633
void preSourceLumi(LuminosityBlockIndex)
Definition: Timing.cc:548
unsigned int nThreads_
Definition: Timing.cc:135
void preOpenFile(std::string const &, bool)
Definition: Timing.cc:556
unsigned int nStreams_
Definition: Timing.cc:134
void preModuleGlobal(GlobalContext const &, ModuleCallingContext const &)
Definition: Timing.cc:564
void postModule(ModuleDescription const &md)
Definition: Timing.cc:562
void postGlobalBeginRun(GlobalContext const &)
Definition: Timing.cc:570
void preSourceRun(RunIndex)
Definition: Timing.cc:552
void postModuleStream(StreamContext const &, ModuleCallingContext const &)
Definition: Timing.cc:592
void accumulateTimeEnd(std::atomic< CountAndTime * > &countAndTime, double &accumulatedTime)
Definition: Timing.cc:656
CountAndTime(unsigned int count, double time)
Definition: Timing.cc:107
ModuleDescription const * moduleDescription() const
void postModuleEvent(StreamContext const &, ModuleCallingContext const &)
Definition: Timing.cc:531
#define CMS_THREAD_GUARD(_var_)
std::atomic< double > last_run_time_
Definition: Timing.cc:119
void postSourceLumi(LuminosityBlockIndex)
Definition: Timing.cc:550
static void pushStack(bool configuredInTopLevelProcess)
Definition: Timing.cc:211
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: Timing.cc:345
~Timing() override
Definition: Timing.cc:334
std::atomic< CountAndTime * > countAndTimeForLock_
Definition: Timing.cc:139
void preLockEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
Definition: Timing.cc:608
static double jobStartTime()
StreamID const & streamID() const
Definition: StreamContext.h:54
static std::string ui2str(unsigned int i)
Definition: Timing.cc:163
void setComment(std::string const &value)
void postGlobalBeginLumi(GlobalContext const &)
Definition: Timing.cc:579
std::atomic< unsigned long > begin_run_count_
Definition: Timing.cc:133
unsigned int value() const
Definition: StreamID.h:42
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void postEventSetupGet(eventsetup::ComponentDescription const *, eventsetup::EventSetupRecordKey const &, eventsetup::DataKey const &)
Definition: Timing.cc:627
std::atomic< unsigned long > total_event_count_
Definition: Timing.cc:131
static std::vector< double > & moduleTimeStack()
Definition: Timing.cc:197
void addToCPUTime(double iTime) override
Definition: Timing.cc:336
double b
Definition: hdecay.h:120
static std::string d2str(double d)
Definition: Timing.cc:157
void add(std::string const &label, ParameterSetDescription const &psetDescription)
double postCommon() const
Definition: Timing.cc:594
edm::serviceregistry::AllArgsMaker< edm::TimingServiceBase, Timing > TimingMaker
Definition: Timing.cc:688
ProcessContext const * processContext() const
Definition: GlobalContext.h:59
void postSourceRun(RunIndex)
Definition: Timing.cc:554
void postModuleGlobal(GlobalContext const &, ModuleCallingContext const &)
Definition: Timing.cc:568
void preBeginJob(PathsAndConsumesOfModulesBase const &, ProcessContext const &)
Definition: Timing.cc:357
HLT enums.
CountAndTime countAndTimeZero_
Definition: Timing.cc:137
void postOpenFile(std::string const &, bool)
Definition: Timing.cc:558
static double getTime()
Definition: Timing.cc:169
void postSourceEvent(StreamID)
Definition: Timing.cc:546
EventID const & eventID() const
Definition: StreamContext.h:59
std::atomic< double > extra_job_cpu_
Definition: Timing.cc:117
static double popStack()
Definition: Timing.cc:202
bool isSubProcess() const
void preSourceEvent(StreamID)
Definition: Timing.cc:544
void preEvent(StreamContext const &)
Definition: Timing.cc:484
std::vector< double > min_events_time_
Definition: Timing.cc:129
unsigned int nSubProcesses_
Definition: Timing.cc:149