CMS 3D CMS Logo

FastTimerService.cc
Go to the documentation of this file.
1 // FIXME
2 // we are by-passing the ME's when filling the plots, so we might need to call the ME's update() by hand
3 
4 
5 // C++ headers
6 #include <cmath>
7 #include <limits>
8 #include <iostream>
9 #include <iomanip>
10 #include <mutex>
11 #include <string>
12 #include <sstream>
13 #include <unordered_set>
14 #include <unordered_map>
15 
16 // boost headers
17 #include <boost/format.hpp>
18 #include <boost/range/irange.hpp>
19 
20 // CMSSW headers
37 
38 // local headers
39 #include "memory_usage.h"
40 
42 
43 namespace {
44 
45  // convert any std::chrono::duration to milliseconds
46  template <class Rep, class Period>
47  double ms(std::chrono::duration<Rep, Period> duration)
48  {
49  return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(duration).count();;
50  }
51 
52  // convert any boost::chrono::duration to milliseconds
53  template <class Rep, class Period>
54  double ms(boost::chrono::duration<Rep, Period> duration)
55  {
56  return boost::chrono::duration_cast<boost::chrono::duration<double, boost::milli>>(duration).count();;
57  }
58 
59  // convert from bytes to kilobytes, rounding down
60  uint64_t kB(uint64_t bytes)
61  {
62  return bytes / 1024;
63  }
64 } // namespace
65 
67 
68 // resources being monitored by the service
69 
70 // Resources
71 
73  time_thread(boost::chrono::nanoseconds::zero()),
74  time_real(boost::chrono::nanoseconds::zero()),
75  allocated(0UL),
76  deallocated(0UL)
77 { }
78 
79 void
81  time_thread = boost::chrono::nanoseconds::zero();
82  time_real = boost::chrono::nanoseconds::zero();
83  allocated = 0UL;
84  deallocated = 0UL;
85 }
86 
89  time_thread += other.time_thread;
90  time_real += other.time_real;
91  allocated += other.allocated;
92  deallocated += other.deallocated;
93  return *this;
94 }
95 
98  Resources result(*this);
99  result += other;
100  return result;
101 }
102 
103 // ResourcesPerModule
104 
106  = default;
107 
108 void
110  total.reset();
111  events = 0;
112 }
113 
116  total += other.total;
117  events += other.events;
118  return *this;
119 }
120 
123  ResourcesPerModule result(*this);
124  result += other;
125  return result;
126 }
127 
128 
129 // ResourcesPerPath
130 
132  = default;
133 
134 void
136  active.reset();
137  total.reset();
138  last = 0;
139  status = false;
140 }
141 
144  active += other.active;
145  total += other.total;
146  last = 0; // summing these makes no sense, reset them instead
147  status = false;
148  return *this;
149 }
150 
153  ResourcesPerPath result(*this);
154  result += other;
155  return result;
156 }
157 
158 
159 // ResourcesPerProcess
160 
162  total(),
163  paths(process.paths_.size()),
164  endpaths(process.endPaths_.size())
165 {
166 }
167 
168 void
170  total.reset();
171  for (auto & path: paths)
172  path.reset();
173  for (auto & path: endpaths)
174  path.reset();
175 }
176 
179  total += other.total;
180  assert(paths.size() == other.paths.size());
181  for (unsigned int i: boost::irange(0ul, paths.size()))
182  paths[i] += other.paths[i];
183  assert(endpaths.size() == other.endpaths.size());
184  for (unsigned int i: boost::irange(0ul, endpaths.size()))
185  endpaths[i] += other.endpaths[i];
186  return *this;
187 }
188 
192  result += other;
193  return result;
194 }
195 
196 
197 // ResourcesPerJob
198 
200  = default;
201 
202 FastTimerService::ResourcesPerJob::ResourcesPerJob(ProcessCallGraph const& job, std::vector<GroupOfModules> const& groups) :
203  total(),
204  highlight( groups.size() ),
205  modules( job.size() ),
206  processes(),
207  events(0)
208 {
209  processes.reserve(job.processes().size());
210  for (auto const& process: job.processes())
211  processes.emplace_back(process);
212 }
213 
214 void
216  total.reset();
217  for (auto & module: highlight)
218  module.reset();
219  for (auto & module: modules)
220  module.reset();
221  for (auto & process: processes)
222  process.reset();
223  events = 0;
224 }
225 
228  total += other.total;
229  assert(highlight.size() == other.highlight.size());
230  for (unsigned int i: boost::irange(0ul, highlight.size()))
231  highlight[i] += other.highlight[i];
232  assert(modules.size() == other.modules.size());
233  for (unsigned int i: boost::irange(0ul, modules.size()))
234  modules[i] += other.modules[i];
235  assert(processes.size() == other.processes.size());
236  for (unsigned int i: boost::irange(0ul, processes.size()))
237  processes[i] += other.processes[i];
238  events += other.events;
239  return *this;
240 }
241 
244  ResourcesPerJob result(*this);
245  result += other;
246  return result;
247 }
248 
249 
250 // per-thread measurements
251 
252 // Measurement
253 
255  = default;
256 
257 void
259  #ifdef DEBUG_THREAD_CONCURRENCY
260  id = std::this_thread::get_id();
261  #endif // DEBUG_THREAD_CONCURRENCY
262  time_thread = boost::chrono::thread_clock::now();
264  allocated = memory_usage::allocated();
265  deallocated = memory_usage::deallocated();
266 }
267 
268 void
270  #ifdef DEBUG_THREAD_CONCURRENCY
271  assert(std::this_thread::get_id() == id);
272  #endif // DEBUG_THREAD_CONCURRENCY
273  auto new_time_thread = boost::chrono::thread_clock::now();
274  auto new_time_real = boost::chrono::high_resolution_clock::now();
275  auto new_allocated = memory_usage::allocated();
276  auto new_deallocated = memory_usage::deallocated();
277  store.time_thread = new_time_thread - time_thread;
278  store.time_real = new_time_real - time_real;
279  store.allocated = new_allocated - allocated;
280  store.deallocated = new_deallocated - deallocated;
281  time_thread = new_time_thread;
282  time_real = new_time_real;
283  allocated = new_allocated;
284  deallocated = new_deallocated;
285 }
286 
288 
290  time_thread_(nullptr),
291  time_thread_byls_(nullptr),
292  time_real_(nullptr),
293  time_real_byls_(nullptr),
294  allocated_(nullptr),
295  allocated_byls_(nullptr),
296  deallocated_(nullptr),
297  deallocated_byls_(nullptr)
298 {
299 }
300 
301 void
303 {
304  // the plots are owned by the DQMStore
305  time_thread_ = nullptr;
306  time_thread_byls_ = nullptr;
307  time_real_ = nullptr;
308  time_real_byls_ = nullptr;
309  allocated_ = nullptr;
310  allocated_byls_ = nullptr;
311  deallocated_ = nullptr;
312  deallocated_byls_ = nullptr;
313 }
314 
315 void
317  DQMStore::IBooker & booker,
318  std::string const& name,
319  std::string const& title,
320  PlotRanges const& ranges,
321  unsigned int lumisections,
322  bool byls)
323 {
324  int time_bins = (int) std::ceil(ranges.time_range / ranges.time_resolution);
325  int mem_bins = (int) std::ceil(ranges.memory_range / ranges.memory_resolution);
326  std::string y_title_ms = (boost::format("events / %.1f ms") % ranges.time_resolution).str();
327  std::string y_title_kB = (boost::format("events / %.1f kB") % ranges.memory_resolution).str();
328 
329  time_thread_ = booker.book1D(
330  name + " time_thread",
331  title + " processing time (cpu)",
332  time_bins, 0., ranges.time_range
333  )->getTH1F();
334  time_thread_->StatOverflows(true);
335  time_thread_->SetXTitle("processing time [ms]");
336  time_thread_->SetYTitle(y_title_ms.c_str());
337 
338  time_real_ = booker.book1D(
339  name + " time_real",
340  title + " processing time (real)",
341  time_bins, 0., ranges.time_range
342  )->getTH1F();
343  time_real_->StatOverflows(true);
344  time_real_->SetXTitle("processing time [ms]");
345  time_real_->SetYTitle(y_title_ms.c_str());
346 
348  {
349  allocated_ = booker.book1D(
350  name + " allocated",
351  title + " allocated memory",
352  mem_bins, 0., ranges.memory_range
353  )->getTH1F();
354  allocated_->StatOverflows(true);
355  allocated_->SetXTitle("memory [kB]");
356  allocated_->SetYTitle(y_title_kB.c_str());
357 
358  deallocated_ = booker.book1D(
359  name + " deallocated",
360  title + " deallocated memory",
361  mem_bins, 0., ranges.memory_range
362  )->getTH1F();
363  deallocated_->StatOverflows(true);
364  deallocated_->SetXTitle("memory [kB]");
365  deallocated_->SetYTitle(y_title_kB.c_str());
366  }
367 
368  if (not byls)
369  return;
370 
372  name + " time_thread_byls",
373  title + " processing time (cpu) vs. lumisection",
374  lumisections, 0.5, lumisections + 0.5,
375  time_bins, 0., std::numeric_limits<double>::infinity(),
376  " ")->getTProfile();
377  time_thread_byls_->StatOverflows(true);
378  time_thread_byls_->SetXTitle("lumisection");
379  time_thread_byls_->SetYTitle("processing time [ms]");
380 
381  time_real_byls_ = booker.bookProfile(
382  name + " time_real_byls",
383  title + " processing time (real) vs. lumisection",
384  lumisections, 0.5, lumisections + 0.5,
385  time_bins, 0., std::numeric_limits<double>::infinity(),
386  " ")->getTProfile();
387  time_real_byls_->StatOverflows(true);
388  time_real_byls_->SetXTitle("lumisection");
389  time_real_byls_->SetYTitle("processing time [ms]");
390 
392  {
393  allocated_byls_ = booker.bookProfile(
394  name + " allocated_byls",
395  title + " allocated memory vs. lumisection",
396  lumisections, 0.5, lumisections + 0.5,
398  " ")->getTProfile();
399  allocated_byls_->StatOverflows(true);
400  allocated_byls_->SetXTitle("lumisection");
401  allocated_byls_->SetYTitle("memory [kB]");
402 
404  name + " deallocated_byls",
405  title + " deallocated memory vs. lumisection",
406  lumisections, 0.5, lumisections + 0.5,
408  " ")->getTProfile();
409  deallocated_byls_->StatOverflows(true);
410  deallocated_byls_->SetXTitle("lumisection");
411  deallocated_byls_->SetYTitle("memory [kB]");
412  }
413 }
414 
415 void
416 FastTimerService::PlotsPerElement::fill(Resources const& data, unsigned int lumisection)
417 {
418  if (time_thread_)
419  time_thread_->Fill(ms(data.time_thread));
420 
421  if (time_thread_byls_)
422  time_thread_byls_->Fill(lumisection, ms(data.time_thread));
423 
424  if (time_real_)
425  time_real_->Fill(ms(data.time_real));
426 
427  if (time_real_byls_)
428  time_real_byls_->Fill(lumisection, ms(data.time_real));
429 
430  if (allocated_)
431  allocated_->Fill(kB(data.allocated));
432 
433  if (allocated_byls_)
434  allocated_byls_->Fill(lumisection, kB(data.allocated));
435 
436  if (deallocated_)
437  deallocated_->Fill(kB(data.deallocated));
438 
439  if (deallocated_byls_)
440  deallocated_byls_->Fill(lumisection, kB(data.deallocated));
441 }
442 
443 void
445 {
446  float total;
447  float fraction;
448 
449  total = ms(data.time_thread);
450  fraction = (total > 0.) ? (ms(part.time_thread) / total) : 0.;
451  if (time_thread_)
452  time_thread_->Fill(total, fraction);
453 
454  if (time_thread_byls_)
455  time_thread_byls_->Fill(lumisection, total, fraction);
456 
457  total = ms(data.time_real);
458  fraction = (total > 0.) ? (ms(part.time_real) / total) : 0.;
459  if (time_real_)
460  time_real_->Fill(total, fraction);
461 
462  if (time_real_byls_)
463  time_real_byls_->Fill(lumisection, total, fraction);
464 
465  total = kB(data.allocated);
466  fraction = (total > 0.) ? (kB(part.allocated) / total) : 0.;
467  if (allocated_)
468  allocated_->Fill(total, fraction);
469 
470  if (allocated_byls_)
471  allocated_byls_->Fill(lumisection, total, fraction);
472 
473  total = kB(data.deallocated);
474  fraction = (total > 0.) ? (kB(part.deallocated) / total) : 0.;
475  if (deallocated_)
476  deallocated_->Fill(total, fraction);
477 
478  if (deallocated_byls_)
479  deallocated_byls_->Fill(lumisection, total, fraction);
480 }
481 
482 
484  total_(),
485  module_counter_(nullptr),
486  module_time_thread_total_(nullptr),
487  module_time_real_total_(nullptr),
488  module_allocated_total_(nullptr),
489  module_deallocated_total_(nullptr)
490 {
491 }
492 
493 void
495 {
496  // the plots are owned by the DQMStore
497  total_.reset();
498  module_counter_ = nullptr;
499  module_time_thread_total_ = nullptr;
500  module_time_real_total_ = nullptr;
501  module_allocated_total_ = nullptr;
502  module_deallocated_total_ = nullptr;
503 }
504 
505 void
507  DQMStore::IBooker & booker,
508  std::string const & prefixDir,
509  ProcessCallGraph const& job,
511  PlotRanges const& ranges,
512  unsigned int lumisections,
513  bool byls)
514 {
515  const std::string basedir = booker.pwd();
516  // booker.setCurrentFolder(basedir + "/path " + path.name_);
517  booker.setCurrentFolder(basedir + "/" + prefixDir + path.name_);
518 
519  total_.book(booker, "path", path.name_, ranges, lumisections, byls);
520 
521  unsigned int bins = path.modules_and_dependencies_.size();
522  module_counter_ = booker.book1DD(
523  "module_counter",
524  "module counter",
525  bins + 1, -0.5, bins + 0.5
526  )->getTH1D();
527  module_counter_->SetYTitle("events");
529  "module_time_thread_total",
530  "total module time (cpu)",
531  bins, -0.5, bins - 0.5
532  )->getTH1D();
533  module_time_thread_total_->SetYTitle("processing time [ms]");
535  "module_time_real_total",
536  "total module time (real)",
537  bins, -0.5, bins - 0.5
538  )->getTH1D();
539  module_time_real_total_->SetYTitle("processing time [ms]");
541  {
543  "module_allocated_total",
544  "total allocated memory",
545  bins, -0.5, bins - 0.5
546  )->getTH1D();
547  module_allocated_total_->SetYTitle("memory [kB]");
549  "module_deallocated_total",
550  "total deallocated memory",
551  bins, -0.5, bins - 0.5
552  )->getTH1D();
553  module_deallocated_total_->SetYTitle("memory [kB]");
554  }
555  for (unsigned int bin: boost::irange(0u, bins)) {
556  auto const& module = job[path.modules_and_dependencies_[bin]];
557  std::string const& label = module.scheduled_ ? module.module_.moduleLabel() : module.module_.moduleLabel() + " (unscheduled)";
558  module_counter_ ->GetXaxis()->SetBinLabel(bin + 1, label.c_str());
559  module_time_thread_total_->GetXaxis()->SetBinLabel(bin + 1, label.c_str());
560  module_time_real_total_ ->GetXaxis()->SetBinLabel(bin + 1, label.c_str());
562  {
563  module_allocated_total_ ->GetXaxis()->SetBinLabel(bin + 1, label.c_str());
564  module_deallocated_total_->GetXaxis()->SetBinLabel(bin + 1, label.c_str());
565  }
566  }
567  module_counter_->GetXaxis()->SetBinLabel(bins + 1, "");
568 
569  booker.setCurrentFolder(basedir);
570 }
571 
572 void
574 {
575  // fill the total path time
576  total_.fill(path.total, ls);
577 
578  // fill the modules that actually ran and the total time spent in each od them
579  for (unsigned int i = 0; i < path.last; ++i) {
580  auto const& module = data.modules[description.modules_and_dependencies_[i]];
581  if (module_counter_)
582  module_counter_->Fill(i);
583 
585  module_time_thread_total_->Fill(i, ms(module.total.time_thread));
586 
588  module_time_real_total_->Fill(i, ms(module.total.time_real));
589 
591  module_allocated_total_->Fill(i, kB(module.total.allocated));
592 
594  module_deallocated_total_->Fill(i, kB(module.total.deallocated));
595  }
596  if (module_counter_ and path.status)
597  module_counter_->Fill(path.last);
598 }
599 
600 
602  event_(),
603  paths_(process.paths_.size()),
604  endpaths_(process.endPaths_.size())
605 {
606 }
607 
608 void
610 {
611  event_.reset();
612  for (auto & path: paths_)
613  path.reset();
614  for (auto & path: endpaths_)
615  path.reset();
616 }
617 
618 void
620  DQMStore::IBooker & booker,
621  ProcessCallGraph const& job,
623  PlotRanges const& event_ranges,
624  PlotRanges const& path_ranges,
625  unsigned int lumisections,
626  bool bypath,
627  bool byls)
628 {
629  const std::string basedir = booker.pwd();
630  event_.book(booker,
631  "process " + process.name_, "process " + process.name_,
632  event_ranges,
633  lumisections,
634  byls);
635  if (bypath) {
636  booker.setCurrentFolder(basedir + "/process " + process.name_ + " paths");
637  for (unsigned int id: boost::irange(0ul, paths_.size()))
638  {
639  paths_[id].book(booker,"path ",
640  job, process.paths_[id],
641  path_ranges,
642  lumisections,
643  byls);
644  }
645  for (unsigned int id: boost::irange(0ul, endpaths_.size()))
646  {
647  endpaths_[id].book(booker,"endpath ",
648  job, process.endPaths_[id],
649  path_ranges,
650  lumisections,
651  byls);
652  }
653  booker.setCurrentFolder(basedir);
654  }
655 }
656 
657 void
659 {
660  // fill process event plots
661  event_.fill(process.total, ls);
662 
663  // fill all paths plots
664  for (unsigned int id: boost::irange(0ul, paths_.size()))
665  paths_[id].fill(description.paths_[id], data, process.paths[id], ls);
666 
667  // fill all endpaths plots
668  for (unsigned int id: boost::irange(0ul, endpaths_.size()))
669  endpaths_[id].fill(description.endPaths_[id], data, process.endpaths[id], ls);
670 }
671 
672 FastTimerService::PlotsPerJob::PlotsPerJob(ProcessCallGraph const& job, std::vector<GroupOfModules> const& groups) :
673  event_(),
674  highlight_(groups.size()),
675  modules_(job.size()),
676  processes_()
677 {
678  processes_.reserve(job.processes().size());
679  for (auto const& process: job.processes())
680  processes_.emplace_back(process);
681 }
682 
683 void
685 {
686  event_.reset();
687  for (auto & module: highlight_)
688  module.reset();
689  for (auto & module: modules_)
690  module.reset();
691  for (auto & process: processes_)
692  process.reset();
693 }
694 
695 void
697  DQMStore::IBooker & booker,
698  ProcessCallGraph const& job,
699  std::vector<GroupOfModules> const& groups,
700  PlotRanges const& event_ranges,
701  PlotRanges const& path_ranges,
702  PlotRanges const& module_ranges,
703  unsigned int lumisections,
704  bool bymodule,
705  bool bypath,
706  bool byls)
707 {
708  const std::string basedir = booker.pwd();
709 
710  // event summary plots
711  event_.book(booker,
712  "event", "Event",
713  event_ranges,
714  lumisections,
715  byls);
716 
717  modules_[job.source().id()].book(booker,
718  "source", "Source",
719  module_ranges,
720  lumisections,
721  byls);
722 
723  // plot the time spent in few given groups of modules
724  for (unsigned int group: boost::irange(0ul, groups.size())) {
725  auto const & label = groups[group].label;
726  highlight_[group].book(booker,
727  "highlight " + label, "Highlight " + label,
728  event_ranges,
729  lumisections,
730  byls);
731  }
732 
733  // plots per subprocess (event, modules, paths and endpaths)
734  for (unsigned int pid: boost::irange(0ul, job.processes().size())) {
735  auto const& process = job.processDescription(pid);
736  processes_[pid].book(booker,
737  job, process,
738  event_ranges,
739  path_ranges,
740  lumisections,
741  bypath,
742  byls);
743 
744  if (bymodule) {
745  booker.setCurrentFolder(basedir + "/process " + process.name_ + " modules");
746  for (unsigned int id: process.modules_)
747  {
748  auto const& module_name = job.module(id).moduleLabel();
749  modules_[id].book(booker,
751  module_ranges,
752  lumisections,
753  byls);
754  }
755  booker.setCurrentFolder(basedir);
756  }
757  }
758 }
759 
760 void
762 {
763  // fill total event plots
764  event_.fill(data.total, ls);
765 
766  // fill highltight plots
767  for (unsigned int group: boost::irange(0ul, highlight_.size()))
768  highlight_[group].fill_fraction(data.total, data.highlight[group], ls);
769 
770  // fill modules plots
771  for (unsigned int id: boost::irange(0ul, modules_.size()))
772  modules_[id].fill(data.modules[id].total, ls);
773 
774  for (unsigned int pid: boost::irange(0ul, processes_.size()))
775  processes_[pid].fill(job.processDescription(pid), data, data.processes[pid], ls);
776 }
777 
778 
780 
782  // configuration
783  callgraph_(),
784  // job configuration
785  concurrent_runs_( 0 ),
786  concurrent_streams_( 0 ),
787  concurrent_threads_( 0 ),
788  print_event_summary_( config.getUntrackedParameter<bool>( "printEventSummary" ) ),
789  print_run_summary_( config.getUntrackedParameter<bool>( "printRunSummary" ) ),
790  print_job_summary_( config.getUntrackedParameter<bool>( "printJobSummary" ) ),
791  // dqm configuration
792  module_id_( edm::ModuleDescription::invalidID() ),
793  enable_dqm_( config.getUntrackedParameter<bool>( "enableDQM" ) ),
794  enable_dqm_bymodule_( config.getUntrackedParameter<bool>( "enableDQMbyModule" ) ),
795  enable_dqm_bypath_( config.getUntrackedParameter<bool>( "enableDQMbyPath" ) ),
796  enable_dqm_byls_( config.getUntrackedParameter<bool>( "enableDQMbyLumiSection" ) ),
797  enable_dqm_bynproc_( config.getUntrackedParameter<bool>( "enableDQMbyProcesses" ) ),
798  dqm_event_ranges_( { config.getUntrackedParameter<double>( "dqmTimeRange" ), // ms
799  config.getUntrackedParameter<double>( "dqmTimeResolution" ), // ms
800  config.getUntrackedParameter<double>( "dqmMemoryRange" ), // kB
801  config.getUntrackedParameter<double>( "dqmMemoryResolution" ) } ), // kB
802  dqm_path_ranges_( { config.getUntrackedParameter<double>( "dqmPathTimeRange" ), // ms
803  config.getUntrackedParameter<double>( "dqmPathTimeResolution" ), // ms
804  config.getUntrackedParameter<double>( "dqmPathMemoryRange" ), // kB
805  config.getUntrackedParameter<double>( "dqmPathMemoryResolution" ) } ), // kB
806  dqm_module_ranges_( { config.getUntrackedParameter<double>( "dqmModuleTimeRange" ), // ms
807  config.getUntrackedParameter<double>( "dqmModuleTimeResolution" ), // ms
808  config.getUntrackedParameter<double>( "dqmModuleMemoryRange" ), // kB
809  config.getUntrackedParameter<double>( "dqmModuleMemoryResolution") } ), // kB
810  dqm_lumisections_range_( config.getUntrackedParameter<unsigned int>( "dqmLumiSectionsRange" ) ),
811  dqm_path_( config.getUntrackedParameter<std::string>("dqmPath" ) ),
812  // highlight configuration
813  highlight_module_psets_( config.getUntrackedParameter<std::vector<edm::ParameterSet>>("highlightModules") ),
814  highlight_modules_( highlight_module_psets_.size()) // filled in postBeginJob()
815 {
816  registry.watchPreallocate( this, & FastTimerService::preallocate );
817  registry.watchPreBeginJob( this, & FastTimerService::preBeginJob );
818  registry.watchPostBeginJob( this, & FastTimerService::postBeginJob );
819  registry.watchPostEndJob( this, & FastTimerService::postEndJob );
820  registry.watchPreGlobalBeginRun( this, & FastTimerService::preGlobalBeginRun );
821 //registry.watchPostGlobalBeginRun( this, & FastTimerService::postGlobalBeginRun );
822 //registry.watchPreGlobalEndRun( this, & FastTimerService::preGlobalEndRun );
823  registry.watchPostGlobalEndRun( this, & FastTimerService::postGlobalEndRun );
824  registry.watchPreStreamBeginRun( this, & FastTimerService::preStreamBeginRun );
825 //registry.watchPostStreamBeginRun( this, & FastTimerService::postStreamBeginRun );
826 //registry.watchPreStreamEndRun( this, & FastTimerService::preStreamEndRun );
827  registry.watchPostStreamEndRun( this, & FastTimerService::postStreamEndRun );
828 //registry.watchPreGlobalBeginLumi( this, & FastTimerService::preGlobalBeginLumi );
829 //registry.watchPostGlobalBeginLumi( this, & FastTimerService::postGlobalBeginLumi );
830 //registry.watchPreGlobalEndLumi( this, & FastTimerService::preGlobalEndLumi );
831 //registry.watchPostGlobalEndLumi( this, & FastTimerService::postGlobalEndLumi );
832  registry.watchPreStreamBeginLumi( this, & FastTimerService::preStreamBeginLumi );
833 //registry.watchPostStreamBeginLumi( this, & FastTimerService::postStreamBeginLumi );
834 //registry.watchPreStreamEndLumi( this, & FastTimerService::preStreamEndLumi );
835  registry.watchPostStreamEndLumi( this, & FastTimerService::postStreamEndLumi );
836 //registry.watchPreEvent( this, & FastTimerService::preEvent );
837  registry.watchPostEvent( this, & FastTimerService::postEvent );
838  registry.watchPrePathEvent( this, & FastTimerService::prePathEvent );
839  registry.watchPostPathEvent( this, & FastTimerService::postPathEvent );
840  registry.watchPreSourceConstruction( this, & FastTimerService::preSourceConstruction);
841 //registry.watchPostSourceConstruction( this, & FastTimerService::postSourceConstruction);
842 //registry.watchPreSourceRun( this, & FastTimerService::preSourceRun );
843 //registry.watchPostSourceRun( this, & FastTimerService::postSourceRun );
844 //registry.watchPreSourceLumi( this, & FastTimerService::preSourceLumi );
845 //registry.watchPostSourceLumi( this, & FastTimerService::postSourceLumi );
846  registry.watchPreSourceEvent( this, & FastTimerService::preSourceEvent );
847  registry.watchPostSourceEvent( this, & FastTimerService::postSourceEvent );
848 //registry.watchPreModuleBeginJob( this, & FastTimerService::preModuleBeginJob );
849 //registry.watchPostModuleBeginJob( this, & FastTimerService::postModuleBeginJob );
850 //registry.watchPreModuleEndJob( this, & FastTimerService::preModuleEndJob );
851 //registry.watchPostModuleEndJob( this, & FastTimerService::postModuleEndJob );
852 //registry.watchPreModuleBeginStream( this, & FastTimerService::preModuleBeginStream );
853 //registry.watchPostModuleBeginStream( this, & FastTimerService::postModuleBeginStream );
854 //registry.watchPreModuleEndStream( this, & FastTimerService::preModuleEndStream );
855 //registry.watchPostModuleEndStream( this, & FastTimerService::postModuleEndStream );
856 //registry.watchPreModuleGlobalBeginRun( this, & FastTimerService::preModuleGlobalBeginRun );
857 //registry.watchPostModuleGlobalBeginRun( this, & FastTimerService::postModuleGlobalBeginRun );
858 //registry.watchPreModuleGlobalEndRun( this, & FastTimerService::preModuleGlobalEndRun );
859 //registry.watchPostModuleGlobalEndRun( this, & FastTimerService::postModuleGlobalEndRun );
860 //registry.watchPreModuleGlobalBeginLumi( this, & FastTimerService::preModuleGlobalBeginLumi );
861 //registry.watchPostModuleGlobalBeginLumi( this, & FastTimerService::postModuleGlobalBeginLumi );
862 //registry.watchPreModuleGlobalEndLumi( this, & FastTimerService::preModuleGlobalEndLumi );
863 //registry.watchPostModuleGlobalEndLumi( this, & FastTimerService::postModuleGlobalEndLumi );
864 //registry.watchPreModuleStreamBeginRun( this, & FastTimerService::preModuleStreamBeginRun );
865 //registry.watchPostModuleStreamBeginRun( this, & FastTimerService::postModuleStreamBeginRun );
866 //registry.watchPreModuleStreamEndRun( this, & FastTimerService::preModuleStreamEndRun );
867 //registry.watchPostModuleStreamEndRun( this, & FastTimerService::postModuleStreamEndRun );
868 //registry.watchPreModuleStreamBeginLumi( this, & FastTimerService::preModuleStreamBeginLumi );
869 //registry.watchPostModuleStreamBeginLumi( this, & FastTimerService::postModuleStreamBeginLumi );
870 //registry.watchPreModuleStreamEndLumi( this, & FastTimerService::preModuleStreamEndLumi );
871 //registry.watchPostModuleStreamEndLumi( this, & FastTimerService::postModuleStreamEndLumi );
872 //registry.watchPreModuleEventPrefetching( this, & FastTimerService::preModuleEventPrefetching );
873 //registry.watchPostModuleEventPrefetching( this, & FastTimerService::postModuleEventPrefetching );
874  registry.watchPreModuleEvent( this, & FastTimerService::preModuleEvent );
875  registry.watchPostModuleEvent( this, & FastTimerService::postModuleEvent );
876  registry.watchPreModuleEventDelayedGet( this, & FastTimerService::preModuleEventDelayedGet );
877  registry.watchPostModuleEventDelayedGet( this, & FastTimerService::postModuleEventDelayedGet );
878 //registry.watchPreEventReadFromSource( this, & FastTimerService::preEventReadFromSource );
879 //registry.watchPostEventReadFromSource( this, & FastTimerService::postEventReadFromSource );
880 }
881 
883 
884 double
886 {
887  // private version, assume "id" is valid
888  auto const& stream = streams_[sid];
889  auto const& module = stream.modules[id];
890  return ms(module.total.time_real);
891 }
892 
893 double
895 {
896  return queryModuleTime_(sid, callgraph_.source().id());
897 }
898 
899 double
901 {
902  auto const& stream = streams_[sid];
903  return ms(stream.total.time_real);
904 }
905 
906 double
908 {
909  unsigned int pid = callgraph_.processId(process);
910  auto const& stream = streams_[sid];
911  return ms(stream.processes[pid].total.time_real);
912 }
913 
914 double
916 {
917  return queryModuleTime_(sid, md.id());
918 }
919 
920 double
922 {
923  if (id < callgraph_.size())
924  return queryModuleTime_(sid, id);
925 
926  // FIXME issue a LogWarning, raise an exception, or return NaN
927  return 0.;
928 }
929 
930 double
932 {
933  for (unsigned int id: boost::irange(0u, callgraph_.size()))
934  if (callgraph_.module(id).moduleLabel() == label)
935  return queryModuleTime_(sid, id);
936 
937  // FIXME issue a LogWarning, raise an exception, or return NaN
938  return 0.;
939 }
940 
941 double
943 {
944  for (unsigned int id: callgraph_.processDescription(process).modules_)
945  if (callgraph_.module(id).moduleLabel() == label)
946  return queryModuleTime_(sid, id);
947 
948  // FIXME issue a LogWarning, raise an exception, or return NaN
949  return 0.;
950 }
951 
952 double
954 {
955  auto const& stream = streams_[sid];
956  for (unsigned int pid: boost::irange(0ul, callgraph_.processes().size()))
957  {
958  auto const& desc = callgraph_.processDescription(pid);
959  for (unsigned int id: boost::irange(0ul, desc.paths_.size()))
960  if (desc.paths_[id].name_ == path)
961  return ms(stream.processes[pid].paths[id].total.time_real);
962  for (unsigned int id: boost::irange(0ul, desc.endPaths_.size()))
963  if (desc.paths_[id].name_ == path)
964  return ms(stream.processes[pid].endpaths[id].total.time_real);
965  }
966 
967  // FIXME issue a LogWarning, raise an exception, or return NaN
968  return 0.;
969 }
970 
971 double
973 {
974  auto const& stream = streams_[sid];
975  unsigned int pid = callgraph_.processId(process);
976  auto const& desc = callgraph_.processDescription(pid);
977  for (unsigned int id: boost::irange(0ul, desc.paths_.size()))
978  if (desc.paths_[id].name_ == path)
979  return ms(stream.processes[pid].paths[id].total.time_real);
980  for (unsigned int id: boost::irange(0ul, desc.endPaths_.size()))
981  if (desc.paths_[id].name_ == path)
982  return ms(stream.processes[pid].endpaths[id].total.time_real);
983 
984  // FIXME issue a LogWarning, raise an exception, or return NaN
985  return 0.;
986 }
987 
988 double
990 {
991  auto const& stream = streams_[sid];
992  for (unsigned int group: boost::irange(0ul, highlight_modules_.size()))
993  if (highlight_modules_[group].label == label)
994  return ms(stream.highlight[group].time_real);
995 
996  // FIXME issue a LogWarning, raise an exception, or return NaN
997  return 0.;
998 }
999 
1000 
1001 void
1003 {
1004  LogDebug("FastTimerService") << "The FastTimerService received is currently not monitoring the signal \"" << signal << "\".\n";
1005 }
1006 
1007 void
1009 {
1010  // warn about each signal only once per job
1011  if (unsupported_signals_.insert(signal).second)
1012  edm::LogWarning("FastTimerService") << "The FastTimerService received the unsupported signal \"" << signal << "\".\n"
1013  << "Please report how to reproduce the issue to cms-hlt@cern.ch .";
1014 }
1015 
1016 void
1018 {
1019  ignoredSignal(__func__);
1020 
1021  // reset the run counters only during the main process being run
1022  if (isFirstSubprocess(gc)) {
1024  run_summary_[gc.runIndex()].reset();
1025  }
1026 }
1027 
1028 void
1030 {
1031  ignoredSignal(__func__);
1032 }
1033 
1034 void
1036 {
1037  ignoredSignal(__func__);
1038 
1039  unsigned int sid = sc.streamID().value();
1040 
1041  // reset counters and book the DQM plots during the main process being run
1042  if (isFirstSubprocess(sc)) {
1043  subprocess_run_check_[sid] = 0;
1044 
1045  // book the DQM plots
1046  if (enable_dqm_) {
1047  // define a callback to book the MonitorElements
1048  auto bookTransactionCallback = [&, this] (DQMStore::IBooker & booker)
1049  {
1050  booker.setCurrentFolder(dqm_path_);
1051  stream_plots_[sid].book(booker, callgraph_,
1060  };
1061 
1062  // book MonitorElements for this stream
1063  edm::Service<DQMStore>()->bookTransaction(bookTransactionCallback, sc.eventID().run(), sid, module_id_);
1064  }
1065  }
1066 }
1067 
1068 
1069 void
1071 {
1075 
1076  if (enable_dqm_bynproc_)
1077  dqm_path_ += (boost::format("/Running %d processes") % concurrent_threads_).str();
1078 
1079  // allocate atomic variables to keep track of the completion of each step, process by process
1080  subprocess_event_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_streams_);
1081  for (unsigned int i = 0; i < concurrent_streams_; ++i)
1083  subprocess_lumisection_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_streams_);
1084  for (unsigned int i = 0; i < concurrent_streams_; ++i)
1086  subprocess_run_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_streams_);
1087  for (unsigned int i = 0; i < concurrent_streams_; ++i)
1088  subprocess_run_check_[i] = 0;
1089  subprocess_global_run_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_streams_);
1090  for (unsigned int i = 0; i < concurrent_runs_; ++i)
1092 
1093  // assign a pseudo module id to the FastTimerService
1095 }
1096 
1097 void
1100 }
1101 
1102 void
1104  callgraph_.preBeginJob(pathsAndConsumes, context);
1105 }
1106 
1107 void
1109  unsigned int modules = callgraph_.size();
1110 
1111  // module highlights
1112  for (unsigned int group: boost::irange(0ul, highlight_module_psets_.size())) {
1113  // copy and sort for faster search via std::binary_search
1114  auto labels = highlight_module_psets_[group].getUntrackedParameter<std::vector<std::string>>("modules");
1115  std::sort(labels.begin(), labels.end());
1116 
1117  highlight_modules_[group].label = highlight_module_psets_[group].getUntrackedParameter<std::string>("label");
1118  highlight_modules_[group].modules.reserve(labels.size());
1119  // convert the module labels in module ids
1120  for (unsigned int i = 0; i < modules; ++i) {
1121  auto const & label = callgraph_.module(i).moduleLabel();
1122  if (std::binary_search(labels.begin(), labels.end(), label))
1123  highlight_modules_[group].modules.push_back(i);
1124  }
1125  }
1126  highlight_module_psets_.clear();
1127 
1128  // allocate the resource counters for each stream, process, path and module
1130  streams_.resize(concurrent_streams_, temp);
1131  run_summary_.resize(concurrent_runs_, temp);
1132  job_summary_ = temp;
1133 
1134  // check that the DQMStore service is available
1135  if (enable_dqm_ and not edm::Service<DQMStore>().isAvailable()) {
1136  // the DQMStore is not available, disable all DQM plots
1137  enable_dqm_ = false;
1138  // FIXME issue a LogWarning ?
1139  }
1140 
1141  // allocate the structures to hold pointers to the DQM plots
1142  if (enable_dqm_)
1144 
1145 }
1146 
1147 void
1149 {
1150  ignoredSignal(__func__);
1151 }
1152 
1153 void
1155 {
1156  ignoredSignal(__func__);
1157 }
1158 
1159 void
1161 {
1162  ignoredSignal(__func__);
1163 
1164  unsigned int sid = sc.streamID().value();
1165 
1166  // merge plots only after the last subprocess has run
1168  if (enable_dqm_ and last) {
1169  DQMStore & store = * edm::Service<DQMStore>();
1171  }
1172 }
1173 
1174 void
1176 {
1177  ignoredSignal(__func__);
1178 }
1179 
1180 void
1182 {
1183  ignoredSignal(__func__);
1184 }
1185 
1186 void
1188 {
1189  ignoredSignal(__func__);
1190 }
1191 
1192 void
1194 {
1195  ignoredSignal(__func__);
1196 }
1197 
1198 void
1200 {
1201  ignoredSignal(__func__);
1202 
1203  // reset counters only during the main process transition
1204  if (isFirstSubprocess(sc)) {
1205  unsigned int sid = sc.streamID().value();
1207  }
1208 }
1209 
1210 void
1212 {
1213  ignoredSignal(__func__);
1214 }
1215 
1216 void
1218 {
1219  ignoredSignal(__func__);
1220 }
1221 
1222 void
1224  ignoredSignal(__func__);
1225 
1226  unsigned int sid = sc.streamID().value();
1227 
1228  // merge plots only after the last subprocess has run
1230  if (enable_dqm_ and last) {
1231  DQMStore & store = * edm::Service<DQMStore>();
1233  }
1234 }
1235 
1236 void
1238 {
1239  ignoredSignal(__func__);
1240 }
1241 
1242 void
1244 {
1245  ignoredSignal(__func__);
1246 
1247  // handle the summaries only after the last subprocess has run
1249  if (print_run_summary_ and last) {
1250  edm::LogVerbatim out("FastReport");
1251  printSummary(out, run_summary_[gc.runIndex()], "Run");
1252  }
1253 }
1254 
1255 void
1257 {
1258  ignoredSignal(__func__);
1259 }
1260 
1261 void
1263 {
1264  ignoredSignal(__func__);
1265 }
1266 
1267 void
1269 {
1270  ignoredSignal(__func__);
1271 }
1272 
1273 void
1275 {
1276  ignoredSignal(__func__);
1277 }
1278 
1279 void
1281 {
1282  if (print_job_summary_) {
1283  edm::LogVerbatim out("FastReport");
1284  printSummary(out, job_summary_, "Job");
1285  }
1286 }
1287 
1288 
1289 template <typename T>
1291 {
1292  out << "FastReport ";
1293  if (label.size() < 60)
1294  for (unsigned int i = (60-label.size()) / 2; i > 0; --i)
1295  out << '-';
1296  out << ' ' << label << " Summary ";
1297  if (label.size() < 60)
1298  for (unsigned int i = (59-label.size()) / 2; i > 0; --i)
1299  out << '-';
1300  out << '\n';
1301 }
1302 
1303 template <typename T>
1305 {
1306  out << "FastReport CPU time Real time Allocated Deallocated " << label << "\n";
1307  // FastReport ######.### ms ######.### ms +######### kB -######### kB ...
1308 }
1309 
1310 template <typename T>
1312 {
1313  out << boost::format("FastReport %10.3f ms %10.3f ms %+10d kB %+10d kB %s\n")
1314  % ms(data.time_thread)
1315  % ms(data.time_real)
1316  % kB(data.allocated)
1317  % kB(data.deallocated)
1318  % label;
1319 }
1320 
1321 template <typename T>
1323 {
1324  printHeader(out, "Event");
1325  printEventHeader(out, "Modules");
1326  auto const& source_d = callgraph_.source();
1327  auto const& source = data.modules[source_d.id()];
1328  printEventLine(out, source.total, source_d.moduleLabel());
1329  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1330  auto const& proc_d = callgraph_.processDescription(i);
1331  auto const& proc = data.processes[i];
1332  printEventLine(out, proc.total, "process " + proc_d.name_);
1333  for (unsigned int m: proc_d.modules_) {
1334  auto const& module_d = callgraph_.module(m);
1335  auto const& module = data.modules[m];
1336  printEventLine(out, module.total, " " + module_d.moduleLabel());
1337  }
1338  }
1339  printEventLine(out, data.total, "total");
1340  out << '\n';
1341  printEventHeader(out, "Processes and Paths");
1342  printEventLine(out, source.total, source_d.moduleLabel());
1343  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1344  auto const& proc_d = callgraph_.processDescription(i);
1345  auto const& proc = data.processes[i];
1346  printEventLine(out, proc.total, "process " + proc_d.name_);
1347  for (unsigned int p = 0; p < proc.paths.size(); ++p) {
1348  auto const& name = proc_d.paths_[p].name_;
1349  auto const& path = proc.paths[p];
1350  printEventLine(out, path.active, name + " (only scheduled modules)");
1351  printEventLine(out, path.total, name + " (including dependencies)");
1352  }
1353  for (unsigned int p = 0; p < proc.endpaths.size(); ++p) {
1354  auto const& name = proc_d.endPaths_[p].name_;
1355  auto const& path = proc.endpaths[p];
1356  printEventLine(out, path.active, name + " (only scheduled modules)");
1357  printEventLine(out, path.total, name + " (including dependencies)");
1358  }
1359  }
1360  printEventLine(out, data.total, "total");
1361  out << '\n';
1362  for (unsigned int group: boost::irange(0ul, highlight_modules_.size())) {
1363  printEventHeader(out, "Highlighted modules");
1364  for (unsigned int m: highlight_modules_[group].modules) {
1365  auto const& module_d = callgraph_.module(m);
1366  auto const& module = data.modules[m];
1367  printEventLine(out, module.total, " " + module_d.moduleLabel());
1368  }
1370  out << '\n';
1371  }
1372 }
1373 
1374 template <typename T>
1375 void FastTimerService::printSummaryHeader(T& out, std::string const& label, bool detailed) const
1376 {
1377  if (detailed)
1378  out << "FastReport CPU time avg. when run Real time avg. when run Alloc, avg. when run Dealloc. avg. when run " << label;
1379  // FastReport ######.### ms ######.### ms ######.### ms ######.### ms +######### kB +######### kB -######### kB -######### kB ...
1380  else
1381  out << "FastReport CPU time avg. Real time avg. Alloc, avg. Dealloc. avg. " << label;
1382  // FastReport ######.### ms ######.### ms +######### kB -######### kB ...
1383 }
1384 
1385 template <typename T>
1387 {
1388  out << boost::format("FastReport %10.3f ms %10.3f ms %+10d kB %+10d kB %s\n")
1389  % (events ? ms(data.time_thread) / events : 0)
1390  % (events ? ms(data.time_real) / events : 0)
1391  % (events ? kB(data.allocated) / events : 0)
1392  % (events ? kB(data.deallocated) / events : 0)
1393  % label;
1394 }
1395 
1396 template <typename T>
1398 {
1399  out << boost::format("FastReport %10.3f ms %10.3f ms %10.3f ms %10.3f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n")
1400  % (events ? ms(data.time_thread) / events : 0) % (active ? ms(data.time_thread) / active : 0)
1401  % (events ? ms(data.time_real) / events : 0) % (active ? ms(data.time_real) / active : 0)
1402  % (events ? kB(data.allocated) / events : 0) % (active ? kB(data.allocated) / active : 0)
1403  % (events ? kB(data.deallocated) / events : 0) % (active ? kB(data.deallocated) / active : 0)
1404  % label;
1405 }
1406 
1407 template <typename T>
1409 {
1410  printHeader(out, label);
1411  printSummaryHeader(out, "Modules", true);
1412  auto const& source_d = callgraph_.source();
1413  auto const& source = data.modules[source_d.id()];
1414  printSummaryLine(out, source.total, data.events, source.events, source_d.moduleLabel());
1415  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1416  auto const& proc_d = callgraph_.processDescription(i);
1417  auto const& proc = data.processes[i];
1418  printSummaryLine(out, proc.total, data.events, "process " + proc_d.name_);
1419  for (unsigned int m: proc_d.modules_) {
1420  auto const& module_d = callgraph_.module(m);
1421  auto const& module = data.modules[m];
1422  printSummaryLine(out, module.total, data.events, module.events, module_d.moduleLabel());
1423  }
1424  }
1425  printSummaryLine(out, data.total, data.events, "total");
1426  out << '\n';
1427  printSummaryHeader(out, "Processes and Paths", false);
1428  printSummaryLine(out, source.total, data.events, source_d.moduleLabel());
1429  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1430  auto const& proc_d = callgraph_.processDescription(i);
1431  auto const& proc = data.processes[i];
1432  printSummaryLine(out, proc.total, data.events, "process " + proc_d.name_);
1433  for (unsigned int p = 0; p < proc.paths.size(); ++p) {
1434  auto const& name = proc_d.paths_[p].name_;
1435  auto const& path = proc.paths[p];
1436  printSummaryLine(out, path.active, data.events, name + " (only scheduled modules)");
1437  printSummaryLine(out, path.total, data.events, name + " (including dependencies)");
1438  }
1439  for (unsigned int p = 0; p < proc.endpaths.size(); ++p) {
1440  auto const& name = proc_d.endPaths_[p].name_;
1441  auto const& path = proc.endpaths[p];
1442  printSummaryLine(out, path.active, data.events, name + " (only scheduled modules)");
1443  printSummaryLine(out, path.total, data.events, name + " (including dependencies)");
1444  }
1445  }
1446  printSummaryLine(out, data.total, data.events, "total");
1447  out << '\n';
1448  for (unsigned int group: boost::irange(0ul, highlight_modules_.size())) {
1449  printSummaryHeader(out, "Highlighted modules", true);
1450  for (unsigned int m: highlight_modules_[group].modules) {
1451  auto const& module_d = callgraph_.module(m);
1452  auto const& module = data.modules[m];
1453  printSummaryLine(out, module.total, data.events, module.events, module_d.moduleLabel());
1454  }
1455  printSummaryLine(out, data.highlight[group], data.events, highlight_modules_[group].label);
1456  out << '\n';
1457  }
1458 }
1459 
1460 // check if this is the first process being signalled
1461 bool
1463 {
1464  return (not sc.processContext()->isSubProcess());
1465 }
1466 
1467 bool
1469 {
1470  return (not gc.processContext()->isSubProcess());
1471 }
1472 
1473 // check if this is the last process being signalled
1474 bool
1475 FastTimerService::isLastSubprocess(std::atomic<unsigned int>& check)
1476 {
1477  // release-acquire semantic guarantees that all writes in this and other threads are visible
1478  // after this operation; full sequentially-consistent ordering is (probably) not needed.
1479  unsigned int old_value = check.fetch_add(1, std::memory_order_acq_rel);
1480  return (old_value == callgraph_.processes().size() - 1);
1481 }
1482 
1483 void
1485 {
1486  ignoredSignal(__func__);
1487 }
1488 
1489 void
1491 {
1492  ignoredSignal(__func__);
1493 
1494  unsigned int pid = callgraph_.processId(* sc.processContext());
1495  unsigned int sid = sc.streamID();
1496  auto & stream = streams_[sid];
1497  auto & process = callgraph_.processDescription(pid);
1498 
1499  // compute the event timing as the sum of all modules' timing
1500  auto & data = stream.processes[pid].total;
1501  for (unsigned int i: process.modules_)
1502  data += stream.modules[i].total;
1503  stream.total += data;
1504 
1505  // handle the summaries and fill the plots only after the last subprocess has run
1507  if (not last)
1508  return;
1509 
1510  // highlighted modules
1511  for (unsigned int group: boost::irange(0ul, highlight_modules_.size()))
1512  for (unsigned int i: highlight_modules_[group].modules)
1513  stream.highlight[group] += stream.modules[i].total;
1514 
1515  // avoid concurrent access to the summary objects
1516  {
1517  std::lock_guard<std::mutex> guard(summary_mutex_);
1518  job_summary_ += stream;
1519  run_summary_[sc.runIndex()] += stream;
1520  }
1521 
1522  if (print_event_summary_) {
1523  edm::LogVerbatim out("FastReport");
1524  printEvent(out, stream);
1525  }
1526 
1527  if (enable_dqm_)
1528  stream_plots_[sid].fill(callgraph_, stream, sc.eventID().luminosityBlock());
1529 }
1530 
1531 void
1533 {
1534  // clear the event counters
1535  auto & stream = streams_[sid];
1536  stream.reset();
1537  ++stream.events;
1538 
1539  subprocess_event_check_[sid] = 0;
1540 
1541  thread().measure();
1542 }
1543 
1544 
1545 void
1547 {
1549  unsigned int id = md.id();
1550  auto & stream = streams_[sid];
1551 
1552  thread().measure_and_store(stream.modules[id].total);
1553  ++stream.modules[id].events;
1554 }
1555 
1556 
1557 void
1559 {
1560  unsigned int sid = sc.streamID().value();
1561  unsigned int pid = callgraph_.processId(* sc.processContext());
1562  unsigned int id = pc.pathID();
1563  auto & stream = streams_[sid];
1564  auto & data = pc.isEndPath() ? stream.processes[pid].endpaths[id] : stream.processes[pid].paths[id];
1565  data.status = false;
1566  data.last = 0;
1567 }
1568 
1569 
1570 void
1572 {
1573  unsigned int sid = sc.streamID().value();
1574  unsigned int pid = callgraph_.processId(* sc.processContext());
1575  unsigned int id = pc.pathID();
1576  auto & stream = streams_[sid];
1577  auto & data = pc.isEndPath() ? stream.processes[pid].endpaths[id] : stream.processes[pid].paths[id];
1578 
1580  unsigned int index = path.modules_on_path_.empty() ? 0 : status.index() + 1;
1581  data.last = path.modules_on_path_.empty() ? 0 : path.last_dependency_of_module_[status.index()];
1582 
1583  for (unsigned int i = 0; i < index; ++i) {
1584  auto const& module = stream.modules[path.modules_on_path_[i]];
1585  data.active += module.total;
1586  }
1587  for (unsigned int i = 0; i < data.last; ++i) {
1588  auto const& module = stream.modules[path.modules_and_dependencies_[i]];
1589  data.total += module.total;
1590  }
1591 }
1592 
1593 void
1595 {
1596  thread().measure();
1597 }
1598 
1599 void
1601 {
1602  edm::ModuleDescription const& md = * mcc.moduleDescription();
1603  unsigned int id = md.id();
1604  unsigned int sid = sc.streamID().value();
1605  auto & stream = streams_[sid];
1606 
1607  thread().measure_and_store(stream.modules[id].total);
1608  ++stream.modules[id].events;
1609 }
1610 
1611 void
1613 {
1614  unsupportedSignal(__func__);
1615 }
1616 
1617 void
1619 {
1620  unsupportedSignal(__func__);
1621 }
1622 
1623 void
1625 {
1626  ignoredSignal(__func__);
1627 }
1628 
1629 void
1631 {
1632  ignoredSignal(__func__);
1633 }
1634 
1635 void
1637 {
1638  ignoredSignal(__func__);
1639 }
1640 
1641 void
1643 {
1644  ignoredSignal(__func__);
1645 }
1646 
1647 void
1649 {
1650  ignoredSignal(__func__);
1651 }
1652 
1653 void
1655 {
1656  ignoredSignal(__func__);
1657 }
1658 
1659 void
1661 {
1662  ignoredSignal(__func__);
1663 }
1664 
1665 void
1667 {
1668  ignoredSignal(__func__);
1669 }
1670 
1671 void
1673 {
1674  ignoredSignal(__func__);
1675 }
1676 
1677 void
1679 {
1680  ignoredSignal(__func__);
1681 }
1682 
1683 void
1685 {
1686  ignoredSignal(__func__);
1687 }
1688 
1689 void
1691 {
1692  ignoredSignal(__func__);
1693 }
1694 
1695 void
1697 {
1698  ignoredSignal(__func__);
1699 }
1700 
1701 void
1703 {
1704  ignoredSignal(__func__);
1705 }
1706 
1707 void
1709 {
1710  ignoredSignal(__func__);
1711 }
1712 
1713 void
1715 {
1716  ignoredSignal(__func__);
1717 }
1718 
1719 void
1721 {
1722  ignoredSignal(__func__);
1723 }
1724 
1725 void
1727 {
1728  ignoredSignal(__func__);
1729 }
1730 
1731 void
1733 {
1734  ignoredSignal(__func__);
1735 }
1736 
1737 void
1739 {
1740  ignoredSignal(__func__);
1741 }
1742 
1743 
1746 {
1747  return threads_.local();
1748 }
1749 
1750 
1751 // describe the module's configuration
1752 void
1754 {
1756  desc.addUntracked<bool>( "printEventSummary", false);
1757  desc.addUntracked<bool>( "printRunSummary", true);
1758  desc.addUntracked<bool>( "printJobSummary", true);
1759  desc.addUntracked<bool>( "enableDQM", true);
1760  desc.addUntracked<bool>( "enableDQMbyModule", false);
1761  desc.addUntracked<bool>( "enableDQMbyPath", false);
1762  desc.addUntracked<bool>( "enableDQMbyLumiSection", false);
1763  desc.addUntracked<bool>( "enableDQMbyProcesses", false);
1764  desc.addUntracked<double>( "dqmTimeRange", 1000. ); // ms
1765  desc.addUntracked<double>( "dqmTimeResolution", 5. ); // ms
1766  desc.addUntracked<double>( "dqmMemoryRange", 1000000. ); // kB
1767  desc.addUntracked<double>( "dqmMemoryResolution", 5000. ); // kB
1768  desc.addUntracked<double>( "dqmPathTimeRange", 100. ); // ms
1769  desc.addUntracked<double>( "dqmPathTimeResolution", 0.5); // ms
1770  desc.addUntracked<double>( "dqmPathMemoryRange", 1000000. ); // kB
1771  desc.addUntracked<double>( "dqmPathMemoryResolution", 5000. ); // kB
1772  desc.addUntracked<double>( "dqmModuleTimeRange", 40. ); // ms
1773  desc.addUntracked<double>( "dqmModuleTimeResolution", 0.2); // ms
1774  desc.addUntracked<double>( "dqmModuleMemoryRange", 100000. ); // kB
1775  desc.addUntracked<double>( "dqmModuleMemoryResolution", 500. ); // kB
1776  desc.addUntracked<unsigned>( "dqmLumiSectionsRange", 2500 ); // ~ 16 hours
1777  desc.addUntracked<std::string>( "dqmPath", "HLT/TimerService");
1778 
1779  edm::ParameterSetDescription highlightModulesDescription;
1780  highlightModulesDescription.addUntracked<std::vector<std::string>>("modules", {});
1781  highlightModulesDescription.addUntracked<std::string>("label", "producers");
1782  desc.addVPSetUntracked("highlightModules", highlightModulesDescription, {});
1783 
1784  // # OBSOLETE - these parameters are ignored, they are left only not to break old configurations
1785  // they will not be printed in the generated cfi.py file
1786  desc.addOptionalNode(edm::ParameterDescription<bool>("useRealTimeClock", true, false), false)->setComment("This parameter is obsolete and will be ignored.");
1787  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingPaths", true, false), false)->setComment("This parameter is obsolete and will be ignored.");
1788  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingModules", true, false), false)->setComment("This parameter is obsolete and will be ignored.");
1789  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingExclusive", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1790  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingSummary", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1791  desc.addOptionalNode(edm::ParameterDescription<bool>("skipFirstPath", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1792  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathActive", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1793  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathTotal", true, false), false)->setComment("This parameter is obsolete and will be ignored.");
1794  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathOverhead", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1795  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathDetails", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1796  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathCounters", true, false), false)->setComment("This parameter is obsolete and will be ignored.");
1797  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathExclusive", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1798  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyModuleType", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1799  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMSummary", false, false), false)->setComment("This parameter is obsolete and will be ignored.");
1800 
1801  descriptions.add("FastTimerService", desc);
1802 }
#define LogDebug(id)
RunNumber_t run() const
Definition: EventID.h:39
size
Write out results.
void preGlobalBeginRun(edm::GlobalContext const &)
void preModuleEventDelayedGet(edm::StreamContext const &, edm::ModuleCallingContext const &)
const bool print_run_summary_
unsigned int maxNumberOfThreads() const
Definition: SystemBounds.h:46
void fill(Resources const &, unsigned int lumisection)
void setComment(std::string const &value)
T getUntrackedParameter(std::string const &, T const &) const
void postStreamBeginRun(edm::StreamContext const &)
double queryEventTime(edm::StreamID) const
void postGlobalEndLumi(edm::GlobalContext const &)
void postGlobalBeginLumi(edm::GlobalContext const &)
void postStreamEndLumi(edm::StreamContext const &)
std::vector< edm::ParameterSet > highlight_module_psets_
void postModuleGlobalEndLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
void preEventReadFromSource(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preGlobalEndRun(edm::GlobalContext const &)
void preBeginJob(edm::PathsAndConsumesOfModulesBase const &, edm::ProcessContext const &)
unsigned int concurrent_threads_
std::vector< unsigned int > modules_and_dependencies_
void postEventReadFromSource(edm::StreamContext const &, edm::ModuleCallingContext const &)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
Definition: CLHEP.h:16
double queryHighlightTime(edm::StreamID sid, std::string const &label) const
const PlotRanges dqm_event_ranges_
void postModuleGlobalEndRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
void postModuleEvent(edm::StreamContext const &, edm::ModuleCallingContext const &)
std::vector< GroupOfModules > highlight_modules_
ResourcesPerJob job_summary_
MonitorElement * bookProfile(Args &&...args)
Definition: DQMStore.h:157
PlotsPerJob(ProcessCallGraph const &job, std::vector< GroupOfModules > const &groups)
unsigned int processId(edm::ProcessContext const &) const
TrainProcessor *const proc
Definition: MVATrainer.cc:101
PlotsPerProcess(ProcessCallGraph::ProcessType const &)
void preGlobalEndLumi(edm::GlobalContext const &)
std::vector< ResourcesPerPath > endpaths
const std::string & pwd(void)
Definition: DQMStore.cc:285
void book(DQMStore::IBooker &, std::string const &, ProcessCallGraph const &, ProcessCallGraph::PathType const &, PlotRanges const &ranges, unsigned int lumisections, bool byls)
double queryModuleTime_(edm::StreamID, unsigned int id) const
bool isFirstSubprocess(edm::StreamContext const &)
const bool enable_dqm_bynproc_
unsigned int concurrent_runs_
boost::chrono::nanoseconds time_real
TH1D * getTH1D(void) const
std::unique_ptr< std::atomic< unsigned int >[]> subprocess_global_run_check_
std::vector< ResourcesPerJob > streams_
RunIndex const & runIndex() const
Definition: StreamContext.h:60
Definition: config.py:1
void postPathEvent(edm::StreamContext const &, edm::PathContext const &, edm::HLTPathStatus const &)
std::vector< PlotsPerElement > highlight_
void preModuleGlobalBeginLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
#define nullptr
void book(DQMStore::IBooker &, ProcessCallGraph const &, ProcessCallGraph::ProcessType const &, PlotRanges const &event_ranges, PlotRanges const &path_ranges, unsigned int lumisections, bool bypath, bool byls)
ResourcesPerProcess & operator+=(ResourcesPerProcess const &other)
LuminosityBlockNumber_t luminosityBlock() const
Definition: EventID.h:40
const bool print_job_summary_
std::string const & moduleLabel() const
const bool enable_dqm_bypath_
edm::ModuleDescription const & source() const
static unsigned int getUniqueID()
Returns a unique id each time called. Intended to be passed to ModuleDescription&#39;s constructor&#39;s modI...
Measurement & thread()
tbb::enumerable_thread_specific< Measurement, tbb::cache_aligned_allocator< Measurement >, tbb::ets_key_per_instance > threads_
void postStreamBeginLumi(edm::StreamContext const &)
void printSummary(T &out, ResourcesPerJob const &, std::string const &label) const
const PlotRanges dqm_path_ranges_
RunIndex const & runIndex() const
Definition: GlobalContext.h:53
unsigned int maxNumberOfStreams() const
Definition: SystemBounds.h:43
ResourcesPerProcess operator+(ResourcesPerProcess const &other) const
ResourcesPerJob operator+(ResourcesPerJob const &other) const
std::vector< ResourcesPerModule > modules
bool isEndPath() const
Definition: PathContext.h:42
void printEvent(T &out, ResourcesPerJob const &) const
void printHeader(T &out, std::string const &label) const
void postModuleStreamEndLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
std::mutex summary_mutex_
ResourcesPerJob & operator+=(ResourcesPerJob const &other)
std::vector< PlotsPerJob > stream_plots_
void printSummaryHeader(T &out, std::string const &label, bool detaile) const
void fill(ProcessCallGraph::ProcessType const &, ResourcesPerJob const &, ResourcesPerProcess const &, unsigned int ls)
double queryModuleTime(edm::StreamID, const edm::ModuleDescription &module) const
void prePathEvent(edm::StreamContext const &, edm::PathContext const &)
unsigned int module_id_
std::vector< ResourcesPerJob > run_summary_
void printEventHeader(T &out, std::string const &label) const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
FastTimerService(const edm::ParameterSet &, edm::ActivityRegistry &)
void preModuleStreamEndLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
void postEvent(edm::StreamContext const &)
std::unique_ptr< std::atomic< unsigned int >[]> subprocess_lumisection_check_
void preBeginJob(edm::PathsAndConsumesOfModulesBase const &, edm::ProcessContext const &)
void postGlobalEndRun(edm::GlobalContext const &)
static uint64_t deallocated()
Definition: memory_usage.cc:75
ModuleDescription const * moduleDescription() const
std::unique_ptr< std::atomic< unsigned int >[]> subprocess_event_check_
void fill_fraction(Resources const &, Resources const &, unsigned int lumisection)
std::vector< ProcessType > const & processes() const
MonitorElement * book1D(Args &&...args)
Definition: DQMStore.h:115
ResourcesPerModule operator+(ResourcesPerModule const &other) const
const double infinity
const unsigned int dqm_lumisections_range_
void postStreamEndRun(edm::StreamContext const &)
std::vector< PathType > paths_
void preModuleEvent(edm::StreamContext const &, edm::ModuleCallingContext const &)
ResourcesPerPath & operator+=(ResourcesPerPath const &other)
std::vector< PlotsPerElement > modules_
ProcessType const & processDescription(unsigned int) const
ParameterDescriptionNode * addOptionalNode(ParameterDescriptionNode const &node, bool writeToCfi)
std::string dqm_path_
void preSourceConstruction(edm::ModuleDescription const &)
void printSummaryLine(T &out, Resources const &data, uint64_t events, std::string const &label) const
unsigned int pathID() const
Definition: PathContext.h:39
format
Some error handling for the usage.
ProcessContext const * processContext() const
Definition: StreamContext.h:63
void printEventLine(T &out, Resources const &data, std::string const &label) const
void mergeAndResetMEsRunSummaryCache(uint32_t run, uint32_t streamId, uint32_t moduleId)
Definition: DQMStore.cc:360
Resources operator+(Resources const &other) const
std::vector< Resources > highlight
const bool enable_dqm_bymodule_
bin
set the eta bin as selection string.
string ranges
Definition: diffTwoXMLs.py:78
StreamID const & streamID() const
Definition: StreamContext.h:57
const PlotRanges dqm_module_ranges_
std::vector< PlotsPerPath > endpaths_
static bool is_available()
Definition: memory_usage.cc:65
const bool enable_dqm_byls_
def ls(path, rec=False)
Definition: eostools.py:348
std::vector< PlotsPerProcess > processes_
void postModuleEventDelayedGet(edm::StreamContext const &, edm::ModuleCallingContext const &)
const bool print_event_summary_
unsigned int value() const
Definition: StreamID.h:46
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:277
unsigned long long uint64_t
Definition: Time.h:15
void postModuleStreamBeginLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
void book(DQMStore::IBooker &, ProcessCallGraph const &, std::vector< GroupOfModules > const &, PlotRanges const &event_ranges, PlotRanges const &path_ranges, PlotRanges const &module_ranges, unsigned int lumisections, bool bymodule, bool bypath, bool byls)
double querySourceTime(edm::StreamID) const
void preModuleStreamEndRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
void postModuleStreamEndRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
part
Definition: HCALResponse.h:20
static uint64_t allocated()
Definition: memory_usage.cc:70
void postModuleStreamBeginRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
TH1F * getTH1F(void) const
void preSourceEvent(edm::StreamID)
boost::chrono::nanoseconds time_thread
void add(std::string const &label, ParameterSetDescription const &psetDescription)
susybsm::MuonSegment ms
Definition: classes.h:31
void preEvent(edm::StreamContext const &)
void postGlobalBeginRun(edm::GlobalContext const &)
ProcessContext const * processContext() const
Definition: GlobalContext.h:56
void preStreamBeginLumi(edm::StreamContext const &)
ResourcesPerProcess(ProcessCallGraph::ProcessType const &process)
void postSourceEvent(edm::StreamID)
void preModuleStreamBeginLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preStreamEndRun(edm::StreamContext const &)
HLT enums.
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
void preModuleStreamBeginRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preStreamEndLumi(edm::StreamContext const &)
void measure_and_store(Resources &store)
ResourcesPerModule & operator+=(ResourcesPerModule const &other)
std::vector< PathType > endPaths_
TProfile * getTProfile(void) const
void event_()
void unsupportedSignal(std::string signal) const
void postModuleEventPrefetching(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preModuleGlobalEndLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
unsigned int size() const
edm::ModuleDescription const & module(unsigned int module) const
void ignoredSignal(std::string signal) const
double queryPathTime(edm::StreamID, std::string const &path) const
void preGlobalBeginLumi(edm::GlobalContext const &)
unsigned int maxNumberOfConcurrentRuns() const
Definition: SystemBounds.h:44
Resources & operator+=(Resources const &other)
void preModuleEventPrefetching(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preSourceConstruction(edm::ModuleDescription const &)
void preModuleGlobalEndRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
tbb::concurrent_unordered_set< std::string > unsupported_signals_
std::vector< PlotsPerPath > paths_
EventID const & eventID() const
Definition: StreamContext.h:59
void postModuleGlobalBeginRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
std::vector< ResourcesPerProcess > processes
static Interceptor::Registry registry("Interceptor")
double queryModuleTimeByLabel(edm::StreamID, std::string const &module) const
boost::date_time::subsecond_duration< boost::posix_time::time_duration, 1000000000 > nanoseconds
def check(config)
Definition: trackerTree.py:14
void book(DQMStore::IBooker &, std::string const &name, std::string const &title, PlotRanges const &ranges, unsigned int lumisections, bool byls)
ProcessCallGraph callgraph_
long double T
void mergeAndResetMEsLuminositySummaryCache(uint32_t run, uint32_t lumi, uint32_t streamId, uint32_t moduleId)
Definition: DQMStore.cc:434
void postModuleGlobalBeginLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
void preStreamBeginRun(edm::StreamContext const &)
std::vector< ResourcesPerPath > paths
MonitorElement * book1DD(Args &&...args)
Definition: DQMStore.h:127
bool isSubProcess() const
ResourcesPerPath operator+(ResourcesPerPath const &other) const
Definition: vlib.h:208
void preModuleGlobalBeginRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
ParameterDescriptionBase * addVPSetUntracked(U const &iLabel, ParameterSetDescription const &validator, std::vector< ParameterSet > const &defaults)
static std::string const source
Definition: EdmProvDump.cc:43
std::unique_ptr< std::atomic< unsigned int >[]> subprocess_run_check_
std::vector< unsigned int > modules_
unsigned int concurrent_streams_
bool isLastSubprocess(std::atomic< unsigned int > &check)
void preallocate(edm::service::SystemBounds const &)
void fill(ProcessCallGraph const &, ResourcesPerJob const &, unsigned int ls)
unsigned int id() const
void fill(ProcessCallGraph::PathType const &, ResourcesPerJob const &, ResourcesPerPath const &, unsigned int lumisection)
unsigned int index() const
Definition: HLTPathStatus.h:55