CMS 3D CMS Logo

FastTimerService.cc
Go to the documentation of this file.
1 // C++ headers
2 #include <cmath>
3 #include <fstream>
4 #include <iomanip>
5 #include <iostream>
6 #include <limits>
7 #include <mutex>
8 #include <sstream>
9 #include <string>
10 #include <unordered_map>
11 #include <unordered_set>
12 
13 // boost headers
14 #include <boost/range/irange.hpp>
15 
16 // {fmt} headers
17 #include <fmt/printf.h>
18 
19 // JSON headers
20 #include <nlohmann/json.hpp>
22 
23 // CMSSW headers
42 #include "FastTimerService.h"
43 
44 using namespace std::literals;
45 
47 
48 namespace {
49 
50  // convert any std::chrono::duration to milliseconds
51  template <class Rep, class Period>
52  double ms(std::chrono::duration<Rep, Period> duration) {
53  return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(duration).count();
54  }
55 
56  // convert any boost::chrono::duration to milliseconds
57  template <class Rep, class Period>
58  double ms(boost::chrono::duration<Rep, Period> duration) {
59  return boost::chrono::duration_cast<boost::chrono::duration<double, boost::milli>>(duration).count();
60  }
61 
62  // convert a std::atomic<boost::chrono::nanoseconds::rep> to milliseconds
63  double ms(std::atomic<boost::chrono::nanoseconds::rep> const& duration) {
64  return boost::chrono::duration_cast<boost::chrono::duration<double, boost::milli>>(
65  boost::chrono::nanoseconds(duration.load()))
66  .count();
67  }
68 
69  // convert from bytes to kilobytes, rounding down
70  uint64_t kB(uint64_t bytes) { return bytes / 1024; }
71 
72  // convert from bytes to kilobytes, rounding down
73  uint64_t kB(std::atomic<uint64_t> const& bytes) { return bytes.load() / 1024; }
74 
75 } // namespace
76 
78 
79 // resources being monitored by the service
80 
81 // Resources
82 
84  : time_thread(boost::chrono::nanoseconds::zero()),
85  time_real(boost::chrono::nanoseconds::zero()),
86  allocated(0ul),
87  deallocated(0ul) {}
88 
90  time_thread = boost::chrono::nanoseconds::zero();
92  allocated = 0ul;
93  deallocated = 0ul;
94 }
95 
97  time_thread += other.time_thread;
98  time_real += other.time_real;
99  allocated += other.allocated;
100  deallocated += other.deallocated;
101  return *this;
102 }
103 
105  time_thread += boost::chrono::nanoseconds(other.time_thread.load());
106  time_real += boost::chrono::nanoseconds(other.time_real.load());
107  allocated += other.allocated.load();
108  deallocated += other.deallocated.load();
109  return *this;
110 }
111 
113  Resources result(*this);
114  result += other;
115  return result;
116 }
117 
119  Resources result(*this);
120  result += other;
121  return result;
122 }
123 
124 // AtomicResources
125 // operation on the whole object are not atomic, as the operations
126 // on the individual fields could be interleaved; however, accumulation
127 // of results should yield the correct result.
128 
130  : time_thread(0ul), time_real(0ul), allocated(0ul), deallocated(0ul) {}
131 
133  : time_thread(other.time_thread.load()),
134  time_real(other.time_real.load()),
135  allocated(other.allocated.load()),
136  deallocated(other.deallocated.load()) {}
137 
139  time_thread = 0ul;
140  time_real = 0ul;
141  allocated = 0ul;
142  deallocated = 0ul;
143 }
144 
146  time_thread = other.time_thread.load();
147  time_real = other.time_real.load();
148  allocated = other.allocated.load();
149  deallocated = other.deallocated.load();
150  return *this;
151 }
152 
154  time_thread += other.time_thread.load();
155  time_real += other.time_real.load();
156  allocated += other.allocated.load();
157  deallocated += other.deallocated.load();
158  return *this;
159 }
160 
162  time_thread += other.time_thread.count();
163  time_real += other.time_real.count();
164  allocated += other.allocated;
165  deallocated += other.deallocated;
166  return *this;
167 }
168 
170  AtomicResources result(*this);
171  result += other;
172  return result;
173 }
174 
176  return other + *this;
177 }
178 
179 // ResourcesPerModule
180 
182 
184  total.reset();
185  events = 0;
186  has_acquire = false;
187 }
188 
190  total += other.total;
191  events += other.events;
192  has_acquire = has_acquire or other.has_acquire;
193  return *this;
194 }
195 
197  ResourcesPerModule const& other) const {
198  ResourcesPerModule result(*this);
199  result += other;
200  return result;
201 }
202 
203 // ResourcesPerPath
204 
206  active.reset();
207  total.reset();
208  last = 0;
209  status = false;
210 }
211 
213  active += other.active;
214  total += other.total;
215  last = 0; // summing these makes no sense, reset them instead
216  status = false;
217  return *this;
218 }
219 
221  ResourcesPerPath result(*this);
222  result += other;
223  return result;
224 }
225 
226 // ResourcesPerProcess
227 
229  : total(), paths(process.paths_.size()), endpaths(process.endPaths_.size()) {}
230 
232  total.reset();
233  for (auto& path : paths)
234  path.reset();
235  for (auto& path : endpaths)
236  path.reset();
237 }
238 
240  ResourcesPerProcess const& other) {
241  total += other.total;
242  assert(paths.size() == other.paths.size());
243  for (unsigned int i : boost::irange(0ul, paths.size()))
244  paths[i] += other.paths[i];
245  assert(endpaths.size() == other.endpaths.size());
246  for (unsigned int i : boost::irange(0ul, endpaths.size()))
247  endpaths[i] += other.endpaths[i];
248  return *this;
249 }
250 
252  ResourcesPerProcess const& other) const {
254  result += other;
255  return result;
256 }
257 
258 // ResourcesPerJob
259 
261  std::vector<GroupOfModules> const& groups)
262  : total(), overhead(), eventsetup(), event(), highlight(groups.size()), modules(job.size()), processes(), events(0) {
263  processes.reserve(job.processes().size());
264  for (auto const& process : job.processes())
265  processes.emplace_back(process);
266 }
267 
269  total.reset();
270  overhead.reset();
271  eventsetup.reset();
272  event.reset();
273  for (auto& module : highlight)
274  module.reset();
275  for (auto& module : modules)
276  module.reset();
277  for (auto& process : processes)
278  process.reset();
279  events = 0;
280 }
281 
283  total += other.total;
284  overhead += other.overhead;
285  eventsetup += other.eventsetup;
286  event += other.event;
287  assert(highlight.size() == other.highlight.size());
288  for (unsigned int i : boost::irange(0ul, highlight.size()))
289  highlight[i] += other.highlight[i];
290  assert(modules.size() == other.modules.size());
291  for (unsigned int i : boost::irange(0ul, modules.size()))
292  modules[i] += other.modules[i];
293  assert(processes.size() == other.processes.size());
294  for (unsigned int i : boost::irange(0ul, processes.size()))
295  processes[i] += other.processes[i];
296  events += other.events;
297  return *this;
298 }
299 
301  ResourcesPerJob result(*this);
302  result += other;
303  return result;
304 }
305 
306 // per-thread measurements
307 
308 // Measurement
309 
311 
313 #ifdef DEBUG_THREAD_CONCURRENCY
314  id = std::this_thread::get_id();
315 #endif // DEBUG_THREAD_CONCURRENCY
316  time_thread = boost::chrono::thread_clock::now();
318  allocated = memory_usage::allocated();
319  deallocated = memory_usage::deallocated();
320 }
321 
323 #ifdef DEBUG_THREAD_CONCURRENCY
324  assert(std::this_thread::get_id() == id);
325 #endif // DEBUG_THREAD_CONCURRENCY
326  auto new_time_thread = boost::chrono::thread_clock::now();
327  auto new_time_real = boost::chrono::high_resolution_clock::now();
328  auto new_allocated = memory_usage::allocated();
329  auto new_deallocated = memory_usage::deallocated();
330  store.time_thread = new_time_thread - time_thread;
331  store.time_real = new_time_real - time_real;
332  store.allocated = new_allocated - allocated;
333  store.deallocated = new_deallocated - deallocated;
334  time_thread = new_time_thread;
335  time_real = new_time_real;
336  allocated = new_allocated;
337  deallocated = new_deallocated;
338 }
339 
341 #ifdef DEBUG_THREAD_CONCURRENCY
342  assert(std::this_thread::get_id() == id);
343 #endif // DEBUG_THREAD_CONCURRENCY
344  auto new_time_thread = boost::chrono::thread_clock::now();
345  auto new_time_real = boost::chrono::high_resolution_clock::now();
346  auto new_allocated = memory_usage::allocated();
347  auto new_deallocated = memory_usage::deallocated();
348  store.time_thread += new_time_thread - time_thread;
349  store.time_real += new_time_real - time_real;
350  store.allocated += new_allocated - allocated;
351  store.deallocated += new_deallocated - deallocated;
352  time_thread = new_time_thread;
353  time_real = new_time_real;
354  allocated = new_allocated;
355  deallocated = new_deallocated;
356 }
357 
359 #ifdef DEBUG_THREAD_CONCURRENCY
360  assert(std::this_thread::get_id() == id);
361 #endif // DEBUG_THREAD_CONCURRENCY
362  auto new_time_thread = boost::chrono::thread_clock::now();
363  auto new_time_real = boost::chrono::high_resolution_clock::now();
364  auto new_allocated = memory_usage::allocated();
365  auto new_deallocated = memory_usage::deallocated();
366  store.time_thread += boost::chrono::duration_cast<boost::chrono::nanoseconds>(new_time_thread - time_thread).count();
367  store.time_real += boost::chrono::duration_cast<boost::chrono::nanoseconds>(new_time_real - time_real).count();
368  store.allocated += new_allocated - allocated;
369  store.deallocated += new_deallocated - deallocated;
370  time_thread = new_time_thread;
371  time_real = new_time_real;
372  allocated = new_allocated;
373  deallocated = new_deallocated;
374 }
375 
377 
379  std::string const& name,
380  std::string const& title,
381  PlotRanges const& ranges,
382  unsigned int lumisections,
383  bool byls) {
384  int time_bins = (int)std::ceil(ranges.time_range / ranges.time_resolution);
385  int mem_bins = (int)std::ceil(ranges.memory_range / ranges.memory_resolution);
386  std::string y_title_ms = fmt::sprintf("events / %.1f ms", ranges.time_resolution);
387  std::string y_title_kB = fmt::sprintf("events / %.1f kB", ranges.memory_resolution);
388 
389  // MonitorElement::setStatOverflows(kTRUE) includes underflows and overflows in the computation of mean and RMS
390  time_thread_ =
391  booker.book1D(name + " time_thread", title + " processing time (cpu)", time_bins, 0., ranges.time_range);
392  time_thread_->setXTitle("processing time [ms]");
393  time_thread_->setYTitle(y_title_ms);
394  time_thread_->setStatOverflows(kTRUE);
395 
396  time_real_ = booker.book1D(name + " time_real", title + " processing time (real)", time_bins, 0., ranges.time_range);
397  time_real_->setXTitle("processing time [ms]");
398  time_real_->setYTitle(y_title_ms);
399  time_real_->setStatOverflows(kTRUE);
400 
402  allocated_ = booker.book1D(name + " allocated", title + " allocated memory", mem_bins, 0., ranges.memory_range);
403  allocated_->setXTitle("memory [kB]");
404  allocated_->setYTitle(y_title_kB);
405  allocated_->setStatOverflows(kTRUE);
406 
407  deallocated_ =
408  booker.book1D(name + " deallocated", title + " deallocated memory", mem_bins, 0., ranges.memory_range);
409  deallocated_->setXTitle("memory [kB]");
410  deallocated_->setYTitle(y_title_kB);
411  deallocated_->setStatOverflows(kTRUE);
412  }
413 
414  if (not byls)
415  return;
416 
417  time_thread_byls_ = booker.bookProfile(name + " time_thread_byls",
418  title + " processing time (cpu) vs. lumisection",
419  lumisections,
420  0.5,
421  lumisections + 0.5,
422  time_bins,
423  0.,
425  " ");
426  time_thread_byls_->setXTitle("lumisection");
427  time_thread_byls_->setYTitle("processing time [ms]");
428  time_thread_byls_->setStatOverflows(kTRUE);
429 
430  time_real_byls_ = booker.bookProfile(name + " time_real_byls",
431  title + " processing time (real) vs. lumisection",
432  lumisections,
433  0.5,
434  lumisections + 0.5,
435  time_bins,
436  0.,
438  " ");
439  time_real_byls_->setXTitle("lumisection");
440  time_real_byls_->setYTitle("processing time [ms]");
441  time_real_byls_->setStatOverflows(kTRUE);
442 
444  allocated_byls_ = booker.bookProfile(name + " allocated_byls",
445  title + " allocated memory vs. lumisection",
446  lumisections,
447  0.5,
448  lumisections + 0.5,
449  mem_bins,
450  0.,
452  " ");
453  allocated_byls_->setXTitle("lumisection");
454  allocated_byls_->setYTitle("memory [kB]");
455  allocated_byls_->setStatOverflows(kTRUE);
456 
457  deallocated_byls_ = booker.bookProfile(name + " deallocated_byls",
458  title + " deallocated memory vs. lumisection",
459  lumisections,
460  0.5,
461  lumisections + 0.5,
462  mem_bins,
463  0.,
465  " ");
466  deallocated_byls_->setXTitle("lumisection");
467  deallocated_byls_->setYTitle("memory [kB]");
468  deallocated_byls_->setStatOverflows(kTRUE);
469  }
470 }
471 
472 void FastTimerService::PlotsPerElement::fill(Resources const& data, unsigned int lumisection) {
473  if (time_thread_)
474  time_thread_->Fill(ms(data.time_thread));
475 
476  if (time_thread_byls_)
477  time_thread_byls_->Fill(lumisection, ms(data.time_thread));
478 
479  if (time_real_)
480  time_real_->Fill(ms(data.time_real));
481 
482  if (time_real_byls_)
483  time_real_byls_->Fill(lumisection, ms(data.time_real));
484 
485  if (allocated_)
486  allocated_->Fill(kB(data.allocated));
487 
488  if (allocated_byls_)
489  allocated_byls_->Fill(lumisection, kB(data.allocated));
490 
491  if (deallocated_)
492  deallocated_->Fill(kB(data.deallocated));
493 
494  if (deallocated_byls_)
495  deallocated_byls_->Fill(lumisection, kB(data.deallocated));
496 }
497 
498 void FastTimerService::PlotsPerElement::fill(AtomicResources const& data, unsigned int lumisection) {
499  if (time_thread_)
500  time_thread_->Fill(ms(boost::chrono::nanoseconds(data.time_thread.load())));
501 
502  if (time_thread_byls_)
503  time_thread_byls_->Fill(lumisection, ms(boost::chrono::nanoseconds(data.time_thread.load())));
504 
505  if (time_real_)
506  time_real_->Fill(ms(boost::chrono::nanoseconds(data.time_real.load())));
507 
508  if (time_real_byls_)
509  time_real_byls_->Fill(lumisection, ms(boost::chrono::nanoseconds(data.time_real.load())));
510 
511  if (allocated_)
512  allocated_->Fill(kB(data.allocated));
513 
514  if (allocated_byls_)
515  allocated_byls_->Fill(lumisection, kB(data.allocated));
516 
517  if (deallocated_)
518  deallocated_->Fill(kB(data.deallocated));
519 
520  if (deallocated_byls_)
521  deallocated_byls_->Fill(lumisection, kB(data.deallocated));
522 }
523 
525  Resources const& part,
526  unsigned int lumisection) {
527  float total;
528  float fraction;
529 
530  total = ms(data.time_thread);
531  fraction = (total > 0.) ? (ms(part.time_thread) / total) : 0.;
532  if (time_thread_)
533  time_thread_->Fill(total, fraction);
534 
535  if (time_thread_byls_)
536  time_thread_byls_->Fill(lumisection, total, fraction);
537 
538  total = ms(data.time_real);
539  fraction = (total > 0.) ? (ms(part.time_real) / total) : 0.;
540  if (time_real_)
541  time_real_->Fill(total, fraction);
542 
543  if (time_real_byls_)
544  time_real_byls_->Fill(lumisection, total, fraction);
545 
546  total = kB(data.allocated);
547  fraction = (total > 0.) ? (kB(part.allocated) / total) : 0.;
548  if (allocated_)
549  allocated_->Fill(total, fraction);
550 
551  if (allocated_byls_)
552  allocated_byls_->Fill(lumisection, total, fraction);
553 
554  total = kB(data.deallocated);
555  fraction = (total > 0.) ? (kB(part.deallocated) / total) : 0.;
556  if (deallocated_)
557  deallocated_->Fill(total, fraction);
558 
559  if (deallocated_byls_)
560  deallocated_byls_->Fill(lumisection, total, fraction);
561 }
562 
564  std::string const& prefixDir,
565  ProcessCallGraph const& job,
567  PlotRanges const& ranges,
568  unsigned int lumisections,
569  bool byls) {
570  const std::string basedir = booker.pwd();
571  booker.setCurrentFolder(basedir + "/" + prefixDir + path.name_);
572 
573  total_.book(booker, "path", path.name_, ranges, lumisections, byls);
574 
575  // MonitorElement::setStatOverflows(kTRUE) includes underflows and overflows in the computation of mean and RMS
576  unsigned int bins = path.modules_and_dependencies_.size();
577  module_counter_ = booker.book1DD("module_counter", "module counter", bins + 1, -0.5, bins + 0.5);
578  module_counter_->setYTitle("events");
579  module_counter_->setStatOverflows(kTRUE);
580  module_time_thread_total_ =
581  booker.book1DD("module_time_thread_total", "total module time (cpu)", bins, -0.5, bins - 0.5);
582  module_time_thread_total_->setYTitle("processing time [ms]");
583  module_time_thread_total_->setStatOverflows(kTRUE);
584  module_time_real_total_ =
585  booker.book1DD("module_time_real_total", "total module time (real)", bins, -0.5, bins - 0.5);
586  module_time_real_total_->setYTitle("processing time [ms]");
587  module_time_real_total_->setStatOverflows(kTRUE);
589  module_allocated_total_ =
590  booker.book1DD("module_allocated_total", "total allocated memory", bins, -0.5, bins - 0.5);
591  module_allocated_total_->setYTitle("memory [kB]");
592  module_allocated_total_->setStatOverflows(kTRUE);
593  module_deallocated_total_ =
594  booker.book1DD("module_deallocated_total", "total deallocated memory", bins, -0.5, bins - 0.5);
595  module_deallocated_total_->setYTitle("memory [kB]");
596  module_deallocated_total_->setStatOverflows(kTRUE);
597  }
598  for (unsigned int bin : boost::irange(0u, bins)) {
599  auto const& module = job[path.modules_and_dependencies_[bin]];
600  std::string const& label =
601  module.scheduled_ ? module.module_.moduleLabel() : module.module_.moduleLabel() + " (unscheduled)";
602  module_counter_->setBinLabel(bin + 1, label);
603  module_time_thread_total_->setBinLabel(bin + 1, label);
604  module_time_real_total_->setBinLabel(bin + 1, label);
606  module_allocated_total_->setBinLabel(bin + 1, label);
607  module_deallocated_total_->setBinLabel(bin + 1, label);
608  }
609  }
610  module_counter_->setBinLabel(bins + 1, "");
611 
612  booker.setCurrentFolder(basedir);
613 }
614 
616  ResourcesPerJob const& data,
617  ResourcesPerPath const& path,
618  unsigned int ls) {
619  // fill the total path time
620  total_.fill(path.total, ls);
621 
622  // fill the modules that actually ran and the total time spent in each od them
623  for (unsigned int i = 0; i < path.last; ++i) {
624  auto const& module = data.modules[description.modules_and_dependencies_[i]];
625  if (module_counter_)
626  module_counter_->Fill(i);
627 
628  if (module_time_thread_total_)
629  module_time_thread_total_->Fill(i, ms(module.total.time_thread));
630 
631  if (module_time_real_total_)
632  module_time_real_total_->Fill(i, ms(module.total.time_real));
633 
634  if (module_allocated_total_)
635  module_allocated_total_->Fill(i, kB(module.total.allocated));
636 
637  if (module_deallocated_total_)
638  module_deallocated_total_->Fill(i, kB(module.total.deallocated));
639  }
640  if (module_counter_ and path.status)
641  module_counter_->Fill(path.last);
642 }
643 
645  : event_(), paths_(process.paths_.size()), endpaths_(process.endPaths_.size()) {}
646 
648  ProcessCallGraph const& job,
650  PlotRanges const& event_ranges,
651  PlotRanges const& path_ranges,
652  unsigned int lumisections,
653  bool bypath,
654  bool byls) {
655  const std::string basedir = booker.pwd();
656  event_.book(booker, "process " + process.name_, "process " + process.name_, event_ranges, lumisections, byls);
657  if (bypath) {
658  booker.setCurrentFolder(basedir + "/process " + process.name_ + " paths");
659  for (unsigned int id : boost::irange(0ul, paths_.size())) {
660  paths_[id].book(booker, "path ", job, process.paths_[id], path_ranges, lumisections, byls);
661  }
662  for (unsigned int id : boost::irange(0ul, endpaths_.size())) {
663  endpaths_[id].book(booker, "endpath ", job, process.endPaths_[id], path_ranges, lumisections, byls);
664  }
665  booker.setCurrentFolder(basedir);
666  }
667 }
668 
670  ResourcesPerJob const& data,
672  unsigned int ls) {
673  // fill process event plots
674  event_.fill(process.total, ls);
675 
676  // fill all paths plots
677  for (unsigned int id : boost::irange(0ul, paths_.size()))
678  paths_[id].fill(description.paths_[id], data, process.paths[id], ls);
679 
680  // fill all endpaths plots
681  for (unsigned int id : boost::irange(0ul, endpaths_.size()))
682  endpaths_[id].fill(description.endPaths_[id], data, process.endpaths[id], ls);
683 }
684 
685 FastTimerService::PlotsPerJob::PlotsPerJob(ProcessCallGraph const& job, std::vector<GroupOfModules> const& groups)
686  : event_(), event_ex_(), overhead_(), highlight_(groups.size()), modules_(job.size()), processes_() {
687  processes_.reserve(job.processes().size());
688  for (auto const& process : job.processes())
689  processes_.emplace_back(process);
690 }
691 
693  ProcessCallGraph const& job,
694  std::vector<GroupOfModules> const& groups,
695  PlotRanges const& event_ranges,
696  PlotRanges const& path_ranges,
697  PlotRanges const& module_ranges,
698  unsigned int lumisections,
699  bool bymodule,
700  bool bypath,
701  bool byls,
702  bool transitions) {
703  const std::string basedir = booker.pwd();
704 
705  // event summary plots
706  event_.book(booker, "event", "Event", event_ranges, lumisections, byls);
707 
708  event_ex_.book(booker, "explicit", "Event (explicit)", event_ranges, lumisections, byls);
709 
710  overhead_.book(booker, "overhead", "Overhead", event_ranges, lumisections, byls);
711 
712  modules_[job.source().id()].book(booker, "source", "Source", module_ranges, lumisections, byls);
713 
714  if (transitions) {
715  lumi_.book(booker, "lumi", "LumiSection transitions", event_ranges, lumisections, byls);
716 
717  run_.book(booker, "run", "Run transtions", event_ranges, lumisections, false);
718  }
719 
720  // plot the time spent in few given groups of modules
721  for (unsigned int group : boost::irange(0ul, groups.size())) {
722  auto const& label = groups[group].label;
723  highlight_[group].book(booker, "highlight " + label, "Highlight " + label, event_ranges, lumisections, byls);
724  }
725 
726  // plots per subprocess (event, modules, paths and endpaths)
727  for (unsigned int pid : boost::irange(0ul, job.processes().size())) {
728  auto const& process = job.processDescription(pid);
729  processes_[pid].book(booker, job, process, event_ranges, path_ranges, lumisections, bypath, byls);
730 
731  if (bymodule) {
732  booker.setCurrentFolder(basedir + "/process " + process.name_ + " modules");
733  for (unsigned int id : process.modules_) {
734  auto const& module_name = job.module(id).moduleLabel();
735  modules_[id].book(booker, module_name, module_name, module_ranges, lumisections, byls);
736  }
737  booker.setCurrentFolder(basedir);
738  }
739  }
740 }
741 
743  // fill total event plots
744  event_.fill(data.total, ls);
745  event_ex_.fill(data.event, ls);
746  overhead_.fill(data.overhead, ls);
747 
748  // fill highltight plots
749  for (unsigned int group : boost::irange(0ul, highlight_.size()))
750  highlight_[group].fill_fraction(data.total, data.highlight[group], ls);
751 
752  // fill modules plots
753  for (unsigned int id : boost::irange(0ul, modules_.size()))
754  modules_[id].fill(data.modules[id].total, ls);
755 
756  for (unsigned int pid : boost::irange(0ul, processes_.size()))
757  processes_[pid].fill(job.processDescription(pid), data, data.processes[pid], ls);
758 }
759 
761  // fill run transition plots
762  run_.fill(data, 0);
763 }
764 
766  // fill lumisection transition plots
767  lumi_.fill(data, ls);
768 }
769 
771 
773  : // configuration
774  callgraph_(),
775  // job configuration
777  concurrent_runs_(0),
780  print_event_summary_(config.getUntrackedParameter<bool>("printEventSummary")),
781  print_run_summary_(config.getUntrackedParameter<bool>("printRunSummary")),
782  print_job_summary_(config.getUntrackedParameter<bool>("printJobSummary")),
783  // JSON configuration
784  //write_json_per_event_(config.getUntrackedParameter<bool>("writeJSONByEvent")),
785  //write_json_per_ls_(config.getUntrackedParameter<bool>("writeJSONByLumiSection")),
786  //write_json_per_run_(config.getUntrackedParameter<bool>("writeJSONByRun")),
787  write_json_summary_(config.getUntrackedParameter<bool>("writeJSONSummary")),
788  json_filename_(config.getUntrackedParameter<std::string>("jsonFileName")),
789  // DQM configuration
790  enable_dqm_(config.getUntrackedParameter<bool>("enableDQM")),
791  enable_dqm_bymodule_(config.getUntrackedParameter<bool>("enableDQMbyModule")),
792  enable_dqm_bypath_(config.getUntrackedParameter<bool>("enableDQMbyPath")),
793  enable_dqm_byls_(config.getUntrackedParameter<bool>("enableDQMbyLumiSection")),
794  enable_dqm_bynproc_(config.getUntrackedParameter<bool>("enableDQMbyProcesses")),
795  enable_dqm_transitions_(config.getUntrackedParameter<bool>("enableDQMTransitions")),
796  dqm_event_ranges_({config.getUntrackedParameter<double>("dqmTimeRange"), // ms
797  config.getUntrackedParameter<double>("dqmTimeResolution"), // ms
798  config.getUntrackedParameter<double>("dqmMemoryRange"), // kB
799  config.getUntrackedParameter<double>("dqmMemoryResolution")}), // kB
800  dqm_path_ranges_({config.getUntrackedParameter<double>("dqmPathTimeRange"), // ms
801  config.getUntrackedParameter<double>("dqmPathTimeResolution"), // ms
802  config.getUntrackedParameter<double>("dqmPathMemoryRange"), // kB
803  config.getUntrackedParameter<double>("dqmPathMemoryResolution")}), // kB
804  dqm_module_ranges_({config.getUntrackedParameter<double>("dqmModuleTimeRange"), // ms
805  config.getUntrackedParameter<double>("dqmModuleTimeResolution"), // ms
806  config.getUntrackedParameter<double>("dqmModuleMemoryRange"), // kB
807  config.getUntrackedParameter<double>("dqmModuleMemoryResolution")}), // kB
808  dqm_lumisections_range_(config.getUntrackedParameter<unsigned int>("dqmLumiSectionsRange")),
809  dqm_path_(config.getUntrackedParameter<std::string>("dqmPath")),
810  // highlight configuration
811  highlight_module_psets_(config.getUntrackedParameter<std::vector<edm::ParameterSet>>("highlightModules")),
812  highlight_modules_(highlight_module_psets_.size()) // filled in postBeginJob()
813 {
814  // start observing when a thread enters or leaves the TBB global thread arena
815  tbb::task_scheduler_observer::observe();
816 
817  // register EDM call backs
818  registry.watchPreallocate(this, &FastTimerService::preallocate);
819  registry.watchPreBeginJob(this, &FastTimerService::preBeginJob);
820  registry.watchPostBeginJob(this, &FastTimerService::postBeginJob);
821  registry.watchPostEndJob(this, &FastTimerService::postEndJob);
822  registry.watchPreGlobalBeginRun(this, &FastTimerService::preGlobalBeginRun);
823  //registry.watchPostGlobalBeginRun( this, & FastTimerService::postGlobalBeginRun );
824  //registry.watchPreGlobalEndRun( this, & FastTimerService::preGlobalEndRun );
825  registry.watchPostGlobalEndRun(this, &FastTimerService::postGlobalEndRun);
826  registry.watchPreStreamBeginRun(this, &FastTimerService::preStreamBeginRun);
827  //registry.watchPostStreamBeginRun( this, & FastTimerService::postStreamBeginRun );
828  //registry.watchPreStreamEndRun( this, & FastTimerService::preStreamEndRun );
829  registry.watchPostStreamEndRun(this, &FastTimerService::postStreamEndRun);
830  registry.watchPreGlobalBeginLumi(this, &FastTimerService::preGlobalBeginLumi);
831  //registry.watchPostGlobalBeginLumi( this, & FastTimerService::postGlobalBeginLumi );
832  //registry.watchPreGlobalEndLumi( this, & FastTimerService::preGlobalEndLumi );
833  registry.watchPostGlobalEndLumi(this, &FastTimerService::postGlobalEndLumi);
834  registry.watchPreStreamBeginLumi(this, &FastTimerService::preStreamBeginLumi);
835  //registry.watchPostStreamBeginLumi( this, & FastTimerService::postStreamBeginLumi );
836  //registry.watchPreStreamEndLumi( this, & FastTimerService::preStreamEndLumi );
837  registry.watchPostStreamEndLumi(this, &FastTimerService::postStreamEndLumi);
838  registry.watchPreEvent(this, &FastTimerService::preEvent);
839  registry.watchPostEvent(this, &FastTimerService::postEvent);
840  registry.watchPrePathEvent(this, &FastTimerService::prePathEvent);
841  registry.watchPostPathEvent(this, &FastTimerService::postPathEvent);
842  registry.watchPreSourceConstruction(this, &FastTimerService::preSourceConstruction);
843  //registry.watchPostSourceConstruction( this, & FastTimerService::postSourceConstruction);
844  registry.watchPreSourceRun(this, &FastTimerService::preSourceRun);
845  registry.watchPostSourceRun(this, &FastTimerService::postSourceRun);
846  registry.watchPreSourceLumi(this, &FastTimerService::preSourceLumi);
847  registry.watchPostSourceLumi(this, &FastTimerService::postSourceLumi);
848  registry.watchPreSourceEvent(this, &FastTimerService::preSourceEvent);
849  registry.watchPostSourceEvent(this, &FastTimerService::postSourceEvent);
850  //registry.watchPreModuleConstruction( this, & FastTimerService::preModuleConstruction);
851  //registry.watchPostModuleConstruction( this, & FastTimerService::postModuleConstruction);
852  //registry.watchPreModuleBeginJob( this, & FastTimerService::preModuleBeginJob );
853  //registry.watchPostModuleBeginJob( this, & FastTimerService::postModuleBeginJob );
854  //registry.watchPreModuleEndJob( this, & FastTimerService::preModuleEndJob );
855  //registry.watchPostModuleEndJob( this, & FastTimerService::postModuleEndJob );
856  //registry.watchPreModuleBeginStream( this, & FastTimerService::preModuleBeginStream );
857  //registry.watchPostModuleBeginStream( this, & FastTimerService::postModuleBeginStream );
858  //registry.watchPreModuleEndStream( this, & FastTimerService::preModuleEndStream );
859  //registry.watchPostModuleEndStream( this, & FastTimerService::postModuleEndStream );
860  registry.watchPreModuleGlobalBeginRun(this, &FastTimerService::preModuleGlobalBeginRun);
861  registry.watchPostModuleGlobalBeginRun(this, &FastTimerService::postModuleGlobalBeginRun);
862  registry.watchPreModuleGlobalEndRun(this, &FastTimerService::preModuleGlobalEndRun);
863  registry.watchPostModuleGlobalEndRun(this, &FastTimerService::postModuleGlobalEndRun);
864  registry.watchPreModuleGlobalBeginLumi(this, &FastTimerService::preModuleGlobalBeginLumi);
865  registry.watchPostModuleGlobalBeginLumi(this, &FastTimerService::postModuleGlobalBeginLumi);
866  registry.watchPreModuleGlobalEndLumi(this, &FastTimerService::preModuleGlobalEndLumi);
867  registry.watchPostModuleGlobalEndLumi(this, &FastTimerService::postModuleGlobalEndLumi);
868  registry.watchPreModuleStreamBeginRun(this, &FastTimerService::preModuleStreamBeginRun);
869  registry.watchPostModuleStreamBeginRun(this, &FastTimerService::postModuleStreamBeginRun);
870  registry.watchPreModuleStreamEndRun(this, &FastTimerService::preModuleStreamEndRun);
871  registry.watchPostModuleStreamEndRun(this, &FastTimerService::postModuleStreamEndRun);
872  registry.watchPreModuleStreamBeginLumi(this, &FastTimerService::preModuleStreamBeginLumi);
873  registry.watchPostModuleStreamBeginLumi(this, &FastTimerService::postModuleStreamBeginLumi);
874  registry.watchPreModuleStreamEndLumi(this, &FastTimerService::preModuleStreamEndLumi);
875  registry.watchPostModuleStreamEndLumi(this, &FastTimerService::postModuleStreamEndLumi);
876  //registry.watchPreModuleEventPrefetching( this, & FastTimerService::preModuleEventPrefetching );
877  //registry.watchPostModuleEventPrefetching( this, & FastTimerService::postModuleEventPrefetching );
878  registry.watchPreModuleEventAcquire(this, &FastTimerService::preModuleEventAcquire);
879  registry.watchPostModuleEventAcquire(this, &FastTimerService::postModuleEventAcquire);
880  registry.watchPreModuleEvent(this, &FastTimerService::preModuleEvent);
881  registry.watchPostModuleEvent(this, &FastTimerService::postModuleEvent);
882  registry.watchPreModuleEventDelayedGet(this, &FastTimerService::preModuleEventDelayedGet);
883  registry.watchPostModuleEventDelayedGet(this, &FastTimerService::postModuleEventDelayedGet);
884  registry.watchPreEventReadFromSource(this, &FastTimerService::preEventReadFromSource);
885  registry.watchPostEventReadFromSource(this, &FastTimerService::postEventReadFromSource);
886  registry.watchPreESModule(this, &FastTimerService::preESModule);
887  registry.watchPostESModule(this, &FastTimerService::postESModule);
888 }
889 
890 void FastTimerService::ignoredSignal(const std::string& signal) const {
891  LogDebug("FastTimerService") << "The FastTimerService received is currently not monitoring the signal \"" << signal
892  << "\".\n";
893 }
894 
896  // warn about each signal only once per job
897  if (unsupported_signals_.insert(signal).second)
898  edm::LogWarning("FastTimerService") << "The FastTimerService received the unsupported signal \"" << signal
899  << "\".\n"
900  << "Please report how to reproduce the issue to cms-hlt@cern.ch .";
901 }
902 
904  ignoredSignal(__func__);
905 
906  // reset the run counters only during the main process being run
907  if (isFirstSubprocess(gc)) {
908  auto index = gc.runIndex();
909  subprocess_global_run_check_[index] = 0;
910  run_transition_[index].reset();
911  run_summary_[index].reset();
912 
913  // book the DQM plots
914  if (enable_dqm_) {
915  // define a callback to book the MonitorElements
916  auto bookTransactionCallback = [&, this](dqm::reco::DQMStore::IBooker& booker, dqm::reco::DQMStore::IGetter&) {
917  auto scope = dqm::reco::DQMStore::IBooker::UseRunScope(booker);
918  // we should really do this, but only DQMStore is allowed to touch it
919  // We could move to postGlobalBeginRun, then the DQMStore has sure set it up.
920  //booker.setRunLumi(gc.luminosityBlockID());
921  booker.setCurrentFolder(dqm_path_);
922  plots_->book(booker,
923  callgraph_,
924  highlight_modules_,
925  dqm_event_ranges_,
926  dqm_path_ranges_,
927  dqm_module_ranges_,
928  dqm_lumisections_range_,
929  enable_dqm_bymodule_,
930  enable_dqm_bypath_,
931  enable_dqm_byls_,
932  enable_dqm_transitions_);
933  };
934 
935  // book MonitorElements for this stream
936  edm::Service<dqm::legacy::DQMStore>()->meBookerGetter(bookTransactionCallback);
937  }
938  }
939 }
940 
941 void FastTimerService::postGlobalBeginRun(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
942 
943 void FastTimerService::preStreamBeginRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
944 
946  concurrent_lumis_ = bounds.maxNumberOfConcurrentLuminosityBlocks();
947  concurrent_runs_ = bounds.maxNumberOfConcurrentRuns();
948  concurrent_streams_ = bounds.maxNumberOfStreams();
949  concurrent_threads_ = bounds.maxNumberOfThreads();
950 
951  if (enable_dqm_bynproc_)
952  dqm_path_ += fmt::sprintf(
953  "/Running on %s with %d streams on %d threads", processor_model, concurrent_streams_, concurrent_threads_);
954 
955  // clean characters that are deemed unsafe for DQM
956  // see the definition of `s_safe` in DQMServices/Core/src/DQMStore.cc
957  auto safe_for_dqm = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# "s;
958  for (auto& c : dqm_path_)
959  if (safe_for_dqm.find(c) == std::string::npos)
960  c = '_';
961 
962  // allocate atomic variables to keep track of the completion of each step, process by process
963  subprocess_event_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_streams_);
964  for (unsigned int i = 0; i < concurrent_streams_; ++i)
965  subprocess_event_check_[i] = 0;
966  subprocess_global_run_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_runs_);
967  for (unsigned int i = 0; i < concurrent_runs_; ++i)
968  subprocess_global_run_check_[i] = 0;
969  subprocess_global_lumi_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_lumis_);
970  for (unsigned int i = 0; i < concurrent_lumis_; ++i)
971  subprocess_global_lumi_check_[i] = 0;
972 
973  // allocate buffers to keep track of the resources spent in the lumi and run transitions
974  lumi_transition_.resize(concurrent_lumis_);
975  run_transition_.resize(concurrent_runs_);
976 }
977 
979  callgraph_.preSourceConstruction(module);
980 }
981 
983  edm::ProcessContext const& context) {
984  callgraph_.preBeginJob(pathsAndConsumes, context);
985 }
986 
988  unsigned int modules = callgraph_.size();
989 
990  // module highlights
991  for (unsigned int group : boost::irange(0ul, highlight_module_psets_.size())) {
992  // copy and sort for faster search via std::binary_search
993  auto labels = highlight_module_psets_[group].getUntrackedParameter<std::vector<std::string>>("modules");
994  std::sort(labels.begin(), labels.end());
995 
996  highlight_modules_[group].label = highlight_module_psets_[group].getUntrackedParameter<std::string>("label");
997  highlight_modules_[group].modules.reserve(labels.size());
998  // convert the module labels in module ids
999  for (unsigned int i = 0; i < modules; ++i) {
1000  auto const& label = callgraph_.module(i).moduleLabel();
1001  if (std::binary_search(labels.begin(), labels.end(), label))
1002  highlight_modules_[group].modules.push_back(i);
1003  }
1004  }
1005  highlight_module_psets_.clear();
1006 
1007  // allocate the resource counters for each stream, process, path and module
1008  ResourcesPerJob temp(callgraph_, highlight_modules_);
1009  streams_.resize(concurrent_streams_, temp);
1010  run_summary_.resize(concurrent_runs_, temp);
1011  job_summary_ = temp;
1012 
1013  // check that the DQMStore service is available
1014  if (enable_dqm_ and not edm::Service<dqm::legacy::DQMStore>().isAvailable()) {
1015  // the DQMStore is not available, disable all DQM plots
1016  enable_dqm_ = false;
1017  edm::LogWarning("FastTimerService") << "The DQMStore is not avalable, the DQM plots will not be generated";
1018  }
1019 
1020  // allocate the structures to hold pointers to the DQM plots
1021  if (enable_dqm_) {
1022  plots_ = std::make_unique<PlotsPerJob>(callgraph_, highlight_modules_);
1023  }
1024 }
1025 
1026 void FastTimerService::postStreamBeginRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1027 
1028 void FastTimerService::preStreamEndRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1029 
1030 void FastTimerService::postStreamEndRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1031 
1033  ignoredSignal(__func__);
1034 
1035  // reset the lumi counters only during the main process being run
1036  if (isFirstSubprocess(gc)) {
1037  auto index = gc.luminosityBlockIndex();
1038  subprocess_global_lumi_check_[index] = 0;
1039  lumi_transition_[index].reset();
1040  }
1041 }
1042 
1043 void FastTimerService::postGlobalBeginLumi(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
1044 
1045 void FastTimerService::preGlobalEndLumi(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
1046 
1048  ignoredSignal(__func__);
1049 
1050  // handle the summaries only after the last subprocess has run
1051  auto index = gc.luminosityBlockIndex();
1052  bool last = isLastSubprocess(subprocess_global_lumi_check_[index]);
1053  if (not last)
1054  return;
1055 
1056  edm::LogVerbatim out("FastReport");
1057  auto const& label =
1058  fmt::sprintf("run %d, lumisection %d", gc.luminosityBlockID().run(), gc.luminosityBlockID().luminosityBlock());
1059  printTransition(out, lumi_transition_[index], label);
1060 
1061  if (enable_dqm_transitions_) {
1062  plots_->fill_lumi(lumi_transition_[index], gc.luminosityBlockID().luminosityBlock());
1063  }
1064 }
1065 
1066 void FastTimerService::preStreamBeginLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1067 
1068 void FastTimerService::postStreamBeginLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1069 
1070 void FastTimerService::preStreamEndLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1071 
1072 void FastTimerService::postStreamEndLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1073 
1074 void FastTimerService::preGlobalEndRun(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
1075 
1077  ignoredSignal(__func__);
1078 
1079  // handle the summaries only after the last subprocess has run
1080  auto index = gc.runIndex();
1081  bool last = isLastSubprocess(subprocess_global_run_check_[index]);
1082  if (not last)
1083  return;
1084 
1085  edm::LogVerbatim out("FastReport");
1086  auto const& label = fmt::sprintf("Run %d", gc.luminosityBlockID().run());
1087  if (print_run_summary_) {
1088  printSummary(out, run_summary_[index], label);
1089  }
1090  printTransition(out, run_transition_[index], label);
1091 
1092  if (enable_dqm_transitions_) {
1093  plots_->fill_run(run_transition_[index]);
1094  }
1095 }
1096 
1097 void FastTimerService::preSourceRun(edm::RunIndex index) { thread().measure_and_accumulate(overhead_); }
1098 
1099 void FastTimerService::postSourceRun(edm::RunIndex index) { thread().measure_and_accumulate(run_transition_[index]); }
1100 
1101 void FastTimerService::preSourceLumi(edm::LuminosityBlockIndex index) { thread().measure_and_accumulate(overhead_); }
1102 
1104  thread().measure_and_accumulate(lumi_transition_[index]);
1105 }
1106 
1108  // stop observing to avoid potential race conditions at exit
1109  tbb::task_scheduler_observer::observe(false);
1110  guard_.finalize();
1111  if (print_job_summary_) {
1112  edm::LogVerbatim out("FastReport");
1113  printSummary(out, job_summary_, "Job");
1114  }
1115  if (write_json_summary_) {
1116  writeSummaryJSON(job_summary_, json_filename_);
1117  }
1118 }
1119 
1120 template <typename T>
1122  out << "FastReport ";
1123  if (label.size() < 60)
1124  for (unsigned int i = (60 - label.size()) / 2; i > 0; --i)
1125  out << '-';
1126  out << ' ' << label << " Summary ";
1127  if (label.size() < 60)
1128  for (unsigned int i = (59 - label.size()) / 2; i > 0; --i)
1129  out << '-';
1130  out << '\n';
1131 }
1132 
1133 template <typename T>
1135  out << "FastReport CPU time Real time Allocated Deallocated " << label << "\n";
1136  // FastReport ########.# ms ########.# ms +######### kB -######### kB ...
1137 }
1138 
1139 template <typename T>
1141  out << fmt::sprintf("FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1142  ms(data.time_thread),
1143  ms(data.time_real),
1144  +static_cast<int64_t>(kB(data.allocated)),
1145  -static_cast<int64_t>(kB(data.deallocated)),
1146  label);
1147 }
1148 
1149 template <typename T>
1151  out << fmt::sprintf("FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1152  ms(boost::chrono::nanoseconds(data.time_thread.load())),
1153  ms(boost::chrono::nanoseconds(data.time_real.load())),
1154  +static_cast<int64_t>(kB(data.allocated)),
1155  -static_cast<int64_t>(kB(data.deallocated)),
1156  label);
1157 }
1158 
1159 template <typename T>
1161  printHeader(out, "Event");
1162  printEventHeader(out, "Modules");
1163  auto const& source_d = callgraph_.source();
1164  auto const& source = data.modules[source_d.id()];
1165  printEventLine(out, source.total, source_d.moduleLabel());
1166  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1167  auto const& proc_d = callgraph_.processDescription(i);
1168  auto const& proc = data.processes[i];
1169  printEventLine(out, proc.total, "process " + proc_d.name_);
1170  for (unsigned int m : proc_d.modules_) {
1171  auto const& module_d = callgraph_.module(m);
1172  auto const& module = data.modules[m];
1173  printEventLine(out, module.total, " " + module_d.moduleLabel());
1174  }
1175  }
1176  printEventLine(out, data.total, "total");
1177  out << '\n';
1178  printEventHeader(out, "Processes and Paths");
1179  printEventLine(out, source.total, source_d.moduleLabel());
1180  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1181  auto const& proc_d = callgraph_.processDescription(i);
1182  auto const& proc = data.processes[i];
1183  printEventLine(out, proc.total, "process " + proc_d.name_);
1184  for (unsigned int p = 0; p < proc.paths.size(); ++p) {
1185  auto const& name = proc_d.paths_[p].name_;
1186  auto const& path = proc.paths[p];
1187  printEventLine(out, path.active, name + " (only scheduled modules)");
1188  printEventLine(out, path.total, name + " (including dependencies)");
1189  }
1190  for (unsigned int p = 0; p < proc.endpaths.size(); ++p) {
1191  auto const& name = proc_d.endPaths_[p].name_;
1192  auto const& path = proc.endpaths[p];
1193  printEventLine(out, path.active, name + " (only scheduled modules)");
1194  printEventLine(out, path.total, name + " (including dependencies)");
1195  }
1196  }
1197  printEventLine(out, data.total, "total");
1198  out << '\n';
1199  for (unsigned int group : boost::irange(0ul, highlight_modules_.size())) {
1200  printEventHeader(out, "Highlighted modules");
1201  for (unsigned int m : highlight_modules_[group].modules) {
1202  auto const& module_d = callgraph_.module(m);
1203  auto const& module = data.modules[m];
1204  printEventLine(out, module.total, " " + module_d.moduleLabel());
1205  }
1206  printEventLine(out, data.highlight[group], highlight_modules_[group].label);
1207  out << '\n';
1208  }
1209 }
1210 
1211 template <typename T>
1212 void FastTimerService::printSummaryHeader(T& out, std::string const& label, bool detailed) const {
1213  // clang-format off
1214  if (detailed)
1215  out << "FastReport CPU time avg. when run Real time avg. when run Alloc. avg. when run Dealloc. avg. when run ";
1216  // FastReport ########.# ms ########.# ms ########.# ms ########.# ms +######### kB +######### kB -######### kB -######### kB ...
1217  else
1218  out << "FastReport CPU time avg. Real time avg. Alloc. avg. Dealloc. avg. ";
1219  // FastReport ########.# ms ########.# ms +######### kB -######### kB ...
1220  out << label << '\n';
1221  // clang-format on
1222 }
1223 
1224 template <typename T>
1226  // clang-format off
1227  out << "FastReport CPU time sched. / depend. Real time sched. / depend. Alloc. sched. / depend. Dealloc. sched. / depend. ";
1228  // FastReport ########.# ms ########.# ms ########.# ms ########.# ms +######### kB +######### kB -######### kB -######### kB ...
1229  out << label << '\n';
1230  // clang-format on
1231 }
1232 
1233 template <typename T>
1235  out << fmt::sprintf(
1236  // clang-format off
1237  "FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1238  // clang-format on
1239  (events ? ms(data.time_thread) / events : 0),
1240  (events ? ms(data.time_real) / events : 0),
1241  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1242  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1243  label);
1244 }
1245 
1246 template <typename T>
1248  T& out, AtomicResources const& data, uint64_t events, uint64_t active, std::string const& label) const {
1249  out << fmt::sprintf(
1250  // clang-format off
1251  "FastReport %10.1f ms %10.1f ms %10.1f ms %10.1f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n",
1252  // clang-format on
1253  (events ? ms(data.time_thread) / events : 0),
1254  (active ? ms(data.time_thread) / active : 0),
1255  (events ? ms(data.time_real) / events : 0),
1256  (active ? ms(data.time_real) / active : 0),
1257  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1258  (active ? +static_cast<int64_t>(kB(data.allocated) / active) : 0),
1259  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1260  (active ? -static_cast<int64_t>(kB(data.deallocated) / active) : 0),
1261  label);
1262 }
1263 
1264 template <typename T>
1266  AtomicResources const& data,
1267  uint64_t events,
1268  std::string const& label) const {
1269  out << fmt::sprintf(
1270  // clang-format off
1271  "FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1272  // clang-format on
1273  (events ? ms(data.time_thread) / events : 0),
1274  (events ? ms(data.time_real) / events : 0),
1275  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1276  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1277  label);
1278 }
1279 
1280 template <typename T>
1282  T& out, Resources const& data, uint64_t events, uint64_t active, std::string const& label) const {
1283  out << fmt::sprintf(
1284  "FastReport %10.1f ms %10.1f ms %10.1f ms %10.1f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n",
1285  (events ? ms(data.time_thread) / events : 0),
1286  (active ? ms(data.time_thread) / active : 0),
1287  (events ? ms(data.time_real) / events : 0),
1288  (active ? ms(data.time_real) / active : 0),
1289  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1290  (active ? +static_cast<int64_t>(kB(data.allocated) / active) : 0),
1291  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1292  (active ? -static_cast<int64_t>(kB(data.deallocated) / active) : 0),
1293  label);
1294 }
1295 
1296 template <typename T>
1298  T& out, Resources const& data, Resources const& total, uint64_t events, std::string const& label) const {
1299  out << fmt::sprintf(
1300  "FastReport %10.1f ms %10.1f ms %10.1f ms %10.1f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n",
1301  (events ? ms(data.time_thread) / events : 0),
1302  (events ? ms(total.time_thread) / events : 0),
1303  (events ? ms(data.time_real) / events : 0),
1304  (events ? ms(total.time_real) / events : 0),
1305  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1306  (events ? +static_cast<int64_t>(kB(total.allocated) / events) : 0),
1307  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1308  (events ? -static_cast<int64_t>(kB(total.deallocated) / events) : 0),
1309  label);
1310 }
1311 
1312 template <typename T>
1314  printHeader(out, label);
1315  printSummaryHeader(out, "Modules", true);
1316  auto const& source_d = callgraph_.source();
1317  auto const& source = data.modules[source_d.id()];
1318  printSummaryLine(out, source.total, data.events, source.events, source_d.moduleLabel());
1319  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1320  auto const& proc_d = callgraph_.processDescription(i);
1321  auto const& proc = data.processes[i];
1322  printSummaryLine(out, proc.total, data.events, "process " + proc_d.name_);
1323  for (unsigned int m : proc_d.modules_) {
1324  auto const& module_d = callgraph_.module(m);
1325  auto const& module = data.modules[m];
1326  printSummaryLine(out, module.total, data.events, module.events, " " + module_d.moduleLabel());
1327  }
1328  }
1329  printSummaryLine(out, data.total, data.events, "total");
1330  printSummaryLine(out, data.overhead, data.events, "other");
1331  printSummaryLine(out, data.eventsetup, data.events, "eventsetup");
1332  out << '\n';
1333  printPathSummaryHeader(out, "Processes and Paths");
1334  printSummaryLine(out, source.total, data.events, source_d.moduleLabel());
1335  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1336  auto const& proc_d = callgraph_.processDescription(i);
1337  auto const& proc = data.processes[i];
1338  printSummaryLine(out, proc.total, data.events, "process " + proc_d.name_);
1339  for (unsigned int p = 0; p < proc.paths.size(); ++p) {
1340  auto const& name = proc_d.paths_[p].name_;
1341  auto const& path = proc.paths[p];
1342  printPathSummaryLine(out, path.active, path.total, data.events, " " + name);
1343  }
1344  for (unsigned int p = 0; p < proc.endpaths.size(); ++p) {
1345  auto const& name = proc_d.endPaths_[p].name_;
1346  auto const& path = proc.endpaths[p];
1347  printPathSummaryLine(out, path.active, path.total, data.events, " " + name);
1348  }
1349  }
1350  printSummaryLine(out, data.total, data.events, "total");
1351  printSummaryLine(out, data.overhead, data.events, "other");
1352  printSummaryLine(out, data.eventsetup, data.events, "eventsetup");
1353  out << '\n';
1354  for (unsigned int group : boost::irange(0ul, highlight_modules_.size())) {
1355  printSummaryHeader(out, "Highlighted modules", true);
1356  for (unsigned int m : highlight_modules_[group].modules) {
1357  auto const& module_d = callgraph_.module(m);
1358  auto const& module = data.modules[m];
1359  printSummaryLine(out, module.total, data.events, module.events, module_d.moduleLabel());
1360  }
1361  printSummaryLine(out, data.highlight[group], data.events, highlight_modules_[group].label);
1362  out << '\n';
1363  }
1364 }
1365 
1366 template <typename T>
1368  printEventHeader(out, "Transition");
1369  printEventLine(out, data, label);
1370 }
1371 
1372 template <typename T>
1374  std::string const& label,
1375  unsigned int events,
1376  T const& data) const {
1377  return json{{"type", type},
1378  {"label", label},
1379  {"events", events},
1380  {"time_thread", ms(data.time_thread)},
1381  {"time_real", ms(data.time_real)},
1382  {"mem_alloc", kB(data.allocated)},
1383  {"mem_free", kB(data.deallocated)}};
1384 }
1385 
1387  return encodeToJSON(module.moduleName(), module.moduleLabel(), data.events, data.total);
1388 }
1389 
1391  json j;
1392 
1393  // write a description of the resources
1394  j["resources"] = json::array({json{{"time_real", "real time"}},
1395  json{{"time_thread", "cpu time"}},
1396  json{{"mem_alloc", "allocated memory"}},
1397  json{{"mem_free", "deallocated memory"}}});
1398 
1399  // write the resources used by the job
1400  j["total"] = encodeToJSON(
1401  "Job", callgraph_.processDescription(0).name_, data.events, data.total + data.overhead + data.eventsetup);
1402 
1403  // write the resources used by every module
1404  j["modules"] = json::array();
1405  for (unsigned int i = 0; i < callgraph_.size(); ++i) {
1406  auto const& module = callgraph_.module(i);
1407  auto const& data_m = data.modules[i];
1408  j["modules"].push_back(encodeToJSON(module, data_m));
1409  }
1410 
1411  // add an entry for the "overhead"
1412  j["modules"].push_back(encodeToJSON("other", "other", data.events, data.overhead));
1413  j["modules"].push_back(encodeToJSON("eventsetup", "eventsetup", data.events, data.eventsetup));
1414 
1415  std::ofstream out(filename);
1416  out << std::setw(2) << j << std::flush;
1417 }
1418 
1419 // check if this is the first process being signalled
1421  return (not sc.processContext()->isSubProcess());
1422 }
1423 
1425  return (not gc.processContext()->isSubProcess());
1426 }
1427 
1428 // check if this is the last process being signalled
1429 bool FastTimerService::isLastSubprocess(std::atomic<unsigned int>& check) {
1430  // release-acquire semantic guarantees that all writes in this and other threads are visible
1431  // after this operation; full sequentially-consistent ordering is (probably) not needed.
1432  unsigned int old_value = check.fetch_add(1, std::memory_order_acq_rel);
1433  return (old_value == callgraph_.processes().size() - 1);
1434 }
1435 
1436 void FastTimerService::preEvent(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1437 
1439  ignoredSignal(__func__);
1440 
1441  unsigned int pid = callgraph_.processId(*sc.processContext());
1442  unsigned int sid = sc.streamID();
1443  auto& stream = streams_[sid];
1444  auto& process = callgraph_.processDescription(pid);
1445 
1446  // measure the event resources as the sum of all modules' resources
1447  auto& data = stream.processes[pid].total;
1448  for (unsigned int id : process.modules_)
1449  data += stream.modules[id].total;
1450  stream.total += data;
1451 
1452  // handle the summaries and fill the plots only after the last subprocess has run
1453  bool last = isLastSubprocess(subprocess_event_check_[sid]);
1454  if (not last)
1455  return;
1456 
1457  // measure the event resources explicitly
1458  stream.event_measurement.measure_and_store(stream.event);
1459 
1460  // add to the event resources those used by source (which is not part of any process)
1461  unsigned int id = 0;
1462  stream.total += stream.modules[id].total;
1463 
1464  // highlighted modules
1465  for (unsigned int group : boost::irange(0ul, highlight_modules_.size()))
1466  for (unsigned int i : highlight_modules_[group].modules)
1467  stream.highlight[group] += stream.modules[i].total;
1468 
1469  // avoid concurrent access to the summary objects
1470  {
1471  std::lock_guard<std::mutex> guard(summary_mutex_);
1472  job_summary_ += stream;
1473  run_summary_[sc.runIndex()] += stream;
1474  }
1475 
1476  if (print_event_summary_) {
1477  edm::LogVerbatim out("FastReport");
1478  printEvent(out, stream);
1479  }
1480 
1481  if (enable_dqm_) {
1482  plots_->fill(callgraph_, stream, sc.eventID().luminosityBlock());
1483  }
1484 }
1485 
1487  // clear the event counters
1488  auto& stream = streams_[sid];
1489  stream.reset();
1490  ++stream.events;
1491 
1492  subprocess_event_check_[sid] = 0;
1493 
1494  // reuse the same measurement for the Source module and for the explicit begin of the Event
1495  auto& measurement = thread();
1496  measurement.measure_and_accumulate(stream.overhead);
1497  stream.event_measurement = measurement;
1498 }
1499 
1501  edm::ModuleDescription const& md = callgraph_.source();
1502  unsigned int id = md.id();
1503  auto& stream = streams_[sid];
1504  auto& module = stream.modules[id];
1505 
1506  thread().measure_and_store(module.total);
1507  ++stream.modules[id].events;
1508 }
1509 
1511  unsigned int sid = sc.streamID().value();
1512  unsigned int pid = callgraph_.processId(*sc.processContext());
1513  unsigned int id = pc.pathID();
1514  auto& stream = streams_[sid];
1515  auto& data = pc.isEndPath() ? stream.processes[pid].endpaths[id] : stream.processes[pid].paths[id];
1516  data.status = false;
1517  data.last = 0;
1518 }
1519 
1521  edm::PathContext const& pc,
1522  edm::HLTPathStatus const& status) {
1523  unsigned int sid = sc.streamID().value();
1524  unsigned int pid = callgraph_.processId(*sc.processContext());
1525  unsigned int id = pc.pathID();
1526  auto& stream = streams_[sid];
1527  auto& data = pc.isEndPath() ? stream.processes[pid].endpaths[id] : stream.processes[pid].paths[id];
1528 
1529  auto const& path =
1530  pc.isEndPath() ? callgraph_.processDescription(pid).endPaths_[id] : callgraph_.processDescription(pid).paths_[id];
1531  unsigned int index = path.modules_on_path_.empty() ? 0 : status.index() + 1;
1532  data.last = path.modules_on_path_.empty() ? 0 : path.last_dependency_of_module_[status.index()];
1533 
1534  for (unsigned int i = 0; i < index; ++i) {
1535  auto const& module = stream.modules[path.modules_on_path_[i]];
1536  data.active += module.total;
1537  }
1538  for (unsigned int i = 0; i < data.last; ++i) {
1539  auto const& module = stream.modules[path.modules_and_dependencies_[i]];
1540  data.total += module.total;
1541  }
1542 }
1543 
1545  unsigned int sid = sc.streamID().value();
1546  auto& stream = streams_[sid];
1547  thread().measure_and_accumulate(stream.overhead);
1548 }
1549 
1551  edm::ModuleDescription const& md = *mcc.moduleDescription();
1552  unsigned int id = md.id();
1553  unsigned int sid = sc.streamID().value();
1554  auto& stream = streams_[sid];
1555  auto& module = stream.modules[id];
1556 
1557  module.has_acquire = true;
1558  thread().measure_and_store(module.total);
1559 }
1560 
1562  unsigned int sid = sc.streamID().value();
1563  auto& stream = streams_[sid];
1564  thread().measure_and_accumulate(stream.overhead);
1565 }
1566 
1568  edm::ModuleDescription const& md = *mcc.moduleDescription();
1569  unsigned int id = md.id();
1570  unsigned int sid = sc.streamID().value();
1571  auto& stream = streams_[sid];
1572  auto& module = stream.modules[id];
1573 
1574  if (module.has_acquire) {
1575  thread().measure_and_accumulate(module.total);
1576  } else {
1577  thread().measure_and_store(module.total);
1578  }
1579  ++module.events;
1580 }
1581 
1583  unsupportedSignal(__func__);
1584 }
1585 
1587  unsupportedSignal(__func__);
1588 }
1589 
1591  ignoredSignal(__func__);
1592 }
1593 
1595  ignoredSignal(__func__);
1596 }
1597 
1600  auto& stream = streams_[sc.streamID()];
1601  thread().measure_and_accumulate(stream.overhead);
1602  }
1603 }
1604 
1607  edm::ModuleDescription const& md = callgraph_.source();
1608  unsigned int id = md.id();
1609  auto& stream = streams_[sc.streamID()];
1610  auto& module = stream.modules[id];
1611 
1612  thread().measure_and_accumulate(module.total);
1613  }
1614 }
1615 
1617  thread().measure_and_accumulate(overhead_);
1618 }
1619 
1621  auto index = gc.runIndex();
1622  thread().measure_and_accumulate(run_transition_[index]);
1623 }
1624 
1626  thread().measure_and_accumulate(overhead_);
1627 }
1628 
1630  auto index = gc.runIndex();
1631  thread().measure_and_accumulate(run_transition_[index]);
1632 }
1633 
1635  thread().measure_and_accumulate(overhead_);
1636 }
1637 
1639  auto index = gc.luminosityBlockIndex();
1640  thread().measure_and_accumulate(lumi_transition_[index]);
1641 }
1642 
1644  thread().measure_and_accumulate(overhead_);
1645 }
1646 
1648  auto index = gc.luminosityBlockIndex();
1649  thread().measure_and_accumulate(lumi_transition_[index]);
1650 }
1651 
1653  thread().measure_and_accumulate(overhead_);
1654 }
1655 
1657  auto index = sc.runIndex();
1658  thread().measure_and_accumulate(run_transition_[index]);
1659 }
1660 
1662  thread().measure_and_accumulate(overhead_);
1663 }
1664 
1666  auto index = sc.runIndex();
1667  thread().measure_and_accumulate(run_transition_[index]);
1668 }
1669 
1671  thread().measure_and_accumulate(overhead_);
1672 }
1673 
1675  auto index = sc.luminosityBlockIndex();
1676  thread().measure_and_accumulate(lumi_transition_[index]);
1677 }
1678 
1680  thread().measure_and_accumulate(overhead_);
1681 }
1682 
1684  auto index = sc.luminosityBlockIndex();
1685  thread().measure_and_accumulate(lumi_transition_[index]);
1686 }
1687 
1689  auto top = cc.getTopModuleCallingContext();
1690  if (top->type() == edm::ParentContext::Type::kPlaceInPath) {
1691  //Paths are only used when processing an Event
1692  unsigned int sid = top->parent().placeInPathContext()->pathContext()->streamContext()->streamID().value();
1693  auto& stream = streams_[sid];
1694  thread().measure_and_accumulate(stream.overhead);
1695  }
1696 }
1698  edm::ESModuleCallingContext const& cc) {
1699  auto top = cc.getTopModuleCallingContext();
1700  if (top->type() == edm::ParentContext::Type::kPlaceInPath) {
1701  unsigned int sid = top->parent().placeInPathContext()->pathContext()->streamContext()->streamID().value();
1702  auto& stream = streams_[sid];
1703  thread().measure_and_accumulate(stream.eventsetup);
1704  }
1705 }
1706 
1708  auto err = ::pthread_key_create(&key_, retire_thread);
1709  if (err) {
1710  throw cms::Exception("FastTimerService") << "ThreadGuard key creation failed: " << ::strerror(err);
1711  }
1712 }
1713 
1714 // If this is a new thread, register it and return true
1716  auto ptr = ::pthread_getspecific(key_);
1717 
1718  if (not ptr) {
1719  auto p = thread_resources_.emplace_back(std::make_shared<specific_t>(r));
1720  auto pp = new std::shared_ptr<specific_t>(*p);
1721  auto err = ::pthread_setspecific(key_, pp);
1722  if (err) {
1723  throw cms::Exception("FastTimerService") << "ThreadGuard pthread_setspecific failed: " << ::strerror(err);
1724  }
1725  return true;
1726  }
1727  return false;
1728 }
1729 
1730 std::shared_ptr<FastTimerService::ThreadGuard::specific_t>* FastTimerService::ThreadGuard::ptr(void* p) {
1731  return static_cast<std::shared_ptr<specific_t>*>(p);
1732 }
1733 
1734 // called when a thread exits
1736  auto ps = ptr(p);
1737  auto expected = true;
1738  if ((*ps)->live_.compare_exchange_strong(expected, false)) {
1739  // account any resources used or freed by the thread before leaving the TBB pool
1740  (*ps)->measurement_.measure_and_accumulate((*ps)->resource_);
1741  }
1742  delete ps;
1743 }
1744 
1745 // finalize all threads that have not retired
1747  for (auto& p : thread_resources_) {
1748  auto expected = true;
1749  if (p->live_.compare_exchange_strong(expected, false)) {
1750  p->measurement_.measure_and_accumulate(p->resource_);
1751  }
1752  }
1753 }
1754 
1756  return (*ptr(::pthread_getspecific(key_)))->measurement_;
1757 }
1758 
1761  // initialise the measurement point for a thread that has newly joined the TBB pool
1762  thread().measure();
1763  }
1764 }
1765 
1767 
1769 
1770 // describe the module's configuration
1773  desc.addUntracked<bool>("printEventSummary", false);
1774  desc.addUntracked<bool>("printRunSummary", true);
1775  desc.addUntracked<bool>("printJobSummary", true);
1776  // JSON configuration
1777  //desc.addUntracked<bool>("writeJSONByEvent", false);
1778  //desc.addUntracked<bool>("writeJSONByLumiSection", false);
1779  //desc.addUntracked<bool>("writeJSONByRun", false);
1780  desc.addUntracked<bool>("writeJSONSummary", false);
1781  desc.addUntracked<std::string>("jsonFileName", "resources.json");
1782  // DQM configuration
1783  desc.addUntracked<bool>("enableDQM", true);
1784  desc.addUntracked<bool>("enableDQMbyModule", false);
1785  desc.addUntracked<bool>("enableDQMbyPath", false);
1786  desc.addUntracked<bool>("enableDQMbyLumiSection", false);
1787  desc.addUntracked<bool>("enableDQMbyProcesses", false);
1788  desc.addUntracked<bool>("enableDQMTransitions", false);
1789  desc.addUntracked<double>("dqmTimeRange", 1000.); // ms
1790  desc.addUntracked<double>("dqmTimeResolution", 5.); // ms
1791  desc.addUntracked<double>("dqmMemoryRange", 1000000.); // kB
1792  desc.addUntracked<double>("dqmMemoryResolution", 5000.); // kB
1793  desc.addUntracked<double>("dqmPathTimeRange", 100.); // ms
1794  desc.addUntracked<double>("dqmPathTimeResolution", 0.5); // ms
1795  desc.addUntracked<double>("dqmPathMemoryRange", 1000000.); // kB
1796  desc.addUntracked<double>("dqmPathMemoryResolution", 5000.); // kB
1797  desc.addUntracked<double>("dqmModuleTimeRange", 40.); // ms
1798  desc.addUntracked<double>("dqmModuleTimeResolution", 0.2); // ms
1799  desc.addUntracked<double>("dqmModuleMemoryRange", 100000.); // kB
1800  desc.addUntracked<double>("dqmModuleMemoryResolution", 500.); // kB
1801  desc.addUntracked<unsigned>("dqmLumiSectionsRange", 2500); // ~ 16 hours
1802  desc.addUntracked<std::string>("dqmPath", "HLT/TimerService");
1803 
1804  edm::ParameterSetDescription highlightModulesDescription;
1805  highlightModulesDescription.addUntracked<std::vector<std::string>>("modules", {});
1806  highlightModulesDescription.addUntracked<std::string>("label", "producers");
1807  desc.addVPSetUntracked("highlightModules", highlightModulesDescription, {});
1808 
1809  // # OBSOLETE - these parameters are ignored, they are left only not to break old configurations
1810  // they will not be printed in the generated cfi.py file
1811  desc.addOptionalNode(edm::ParameterDescription<bool>("useRealTimeClock", true, false), false)
1812  ->setComment("This parameter is obsolete and will be ignored.");
1813  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingPaths", true, false), false)
1814  ->setComment("This parameter is obsolete and will be ignored.");
1815  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingModules", true, false), false)
1816  ->setComment("This parameter is obsolete and will be ignored.");
1817  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingExclusive", false, false), false)
1818  ->setComment("This parameter is obsolete and will be ignored.");
1819  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingSummary", false, false), false)
1820  ->setComment("This parameter is obsolete and will be ignored.");
1821  desc.addOptionalNode(edm::ParameterDescription<bool>("skipFirstPath", false, false), false)
1822  ->setComment("This parameter is obsolete and will be ignored.");
1823  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathActive", false, false), false)
1824  ->setComment("This parameter is obsolete and will be ignored.");
1825  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathTotal", true, false), false)
1826  ->setComment("This parameter is obsolete and will be ignored.");
1827  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathOverhead", false, false), false)
1828  ->setComment("This parameter is obsolete and will be ignored.");
1829  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathDetails", false, false), false)
1830  ->setComment("This parameter is obsolete and will be ignored.");
1831  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathCounters", true, false), false)
1832  ->setComment("This parameter is obsolete and will be ignored.");
1833  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathExclusive", false, false), false)
1834  ->setComment("This parameter is obsolete and will be ignored.");
1835  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyModuleType", false, false), false)
1836  ->setComment("This parameter is obsolete and will be ignored.");
1837  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMSummary", false, false), false)
1838  ->setComment("This parameter is obsolete and will be ignored.");
1839 
1840  descriptions.add("FastTimerService", desc);
1841 }
1842 
1843 // declare FastTimerService as a framework Service
size
Write out results.
void preGlobalBeginRun(edm::GlobalContext const &)
void preModuleEventDelayedGet(edm::StreamContext const &, edm::ModuleCallingContext const &)
const bool print_run_summary_
constexpr int32_t ceil(float num)
void fill(Resources const &, unsigned int lumisection)
ResourcesPerProcess operator+(ResourcesPerProcess const &other) const
void postStreamBeginRun(edm::StreamContext const &)
ModuleDescription const * moduleDescription() const
void postGlobalEndLumi(edm::GlobalContext const &)
LuminosityBlockNumber_t luminosityBlock() const
void postGlobalBeginLumi(edm::GlobalContext const &)
void on_scheduler_entry(bool worker) final
void postStreamEndLumi(edm::StreamContext const &)
void on_scheduler_exit(bool worker) final
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 &)
void fill_lumi(AtomicResources const &, unsigned int lumisection)
void preSourceLumi(edm::LuminosityBlockIndex)
void printSummary(T &out, ResourcesPerJob const &data, std::string const &label) const
boost::date_time::subsecond_duration< boost::posix_time::time_duration, 1000000000 > nanoseconds
ResourcesPerJob operator+(ResourcesPerJob const &other) const
unsigned int concurrent_threads_
void postEventReadFromSource(edm::StreamContext const &, edm::ModuleCallingContext const &)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
Definition: CLHEP.h:16
const PlotRanges dqm_event_ranges_
void postModuleGlobalEndRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
void preSourceRun(edm::RunIndex)
void postModuleEvent(edm::StreamContext const &, edm::ModuleCallingContext const &)
void unsupportedSignal(const std::string &signal) const
void writeSummaryJSON(ResourcesPerJob const &data, std::string const &filename) const
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:32
const bool write_json_summary_
void book(dqm::reco::DQMStore::IBooker &, ProcessCallGraph const &, ProcessCallGraph::ProcessType const &, PlotRanges const &event_ranges, PlotRanges const &path_ranges, unsigned int lumisections, bool bypath, bool byls)
PlotsPerJob(ProcessCallGraph const &job, std::vector< GroupOfModules > const &groups)
nlohmann::json json
PlotsPerProcess(ProcessCallGraph::ProcessType const &)
void preGlobalEndLumi(edm::GlobalContext const &)
ModuleCallingContext const * getTopModuleCallingContext() const
edm::ModuleDescription const & source() const
virtual std::string pwd()
Definition: DQMStore.cc:16
AtomicResources overhead_
void preESModule(edm::eventsetup::EventSetupRecordKey const &, edm::ESModuleCallingContext const &)
const std::string json_filename_
bool isFirstSubprocess(edm::StreamContext const &)
const bool enable_dqm_bynproc_
void postESModule(edm::eventsetup::EventSetupRecordKey const &, edm::ESModuleCallingContext const &)
unsigned int concurrent_runs_
void postSourceRun(edm::RunIndex)
StreamContext const * streamContext() const
Definition: PathContext.h:31
Definition: config.py:1
void postPathEvent(edm::StreamContext const &, edm::PathContext const &, edm::HLTPathStatus const &)
void preModuleGlobalBeginLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t stream
ResourcesPerProcess & operator+=(ResourcesPerProcess const &other)
void book(dqm::reco::DQMStore::IBooker &, std::string const &, ProcessCallGraph const &, ProcessCallGraph::PathType const &, PlotRanges const &ranges, unsigned int lumisections, bool byls)
assert(be >=bs)
const bool print_job_summary_
const bool enable_dqm_bypath_
void book(dqm::reco::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, bool transitions)
AtomicResources operator+(AtomicResources const &other) const
Measurement & thread()
LuminosityBlockNumber_t luminosityBlock() const
Definition: EventID.h:39
void printSummary(const std::map< unsigned int, SiStripDetSummary::Values > &map)
edm::ModuleDescription const & module(unsigned int module) const
void postStreamBeginLumi(edm::StreamContext const &)
char const * label
void postModuleStreamEndLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
std::vector< ProcessType > const & processes() const
MonitorElement * book1DD(TString const &name, TString const &title, int nchX, double lowX, double highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:155
ResourcesPerJob & operator+=(ResourcesPerJob const &other)
virtual void setXTitle(std::string const &title)
unsigned int id() const
void fill(ProcessCallGraph::ProcessType const &, ResourcesPerJob const &, ResourcesPerProcess const &, unsigned int ls)
ResourcesPerModule operator+(ResourcesPerModule const &other) const
void printEvent(T &out, ResourcesPerJob const &) const
void prePathEvent(edm::StreamContext const &, edm::PathContext const &)
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:399
const std::string processor_model
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
FastTimerService(const edm::ParameterSet &, edm::ActivityRegistry &)
void preModuleStreamEndLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
StreamID const & streamID() const
Definition: StreamContext.h:54
void postEvent(edm::StreamContext const &)
void postGlobalEndRun(edm::GlobalContext const &)
static uint64_t deallocated()
Definition: memory_usage.cc:88
void fill_fraction(Resources const &, Resources const &, unsigned int lumisection)
const double infinity
void postStreamEndRun(edm::StreamContext const &)
void preModuleEvent(edm::StreamContext const &, edm::ModuleCallingContext const &)
ResourcesPerPath & operator+=(ResourcesPerPath const &other)
Resources operator+(Resources const &other) const
unsigned int concurrent_lumis_
void printSummaryLine(T &out, Resources const &data, uint64_t events, std::string const &label) const
bool register_thread(FastTimerService::AtomicResources &r)
void printPathSummaryLine(T &out, Resources const &data, Resources const &total, uint64_t events, std::string const &label) const
json encodeToJSON(std::string const &type, std::string const &label, unsigned int events, T const &data) const
ProcessContext const * processContext() const
Definition: StreamContext.h:63
const bool enable_dqm_transitions_
LuminosityBlockIndex const & luminosityBlockIndex() const
Definition: GlobalContext.h:62
void printSummaryHeader(T &out, std::string const &label, bool detailed) const
ProcessContext const * processContext() const
Definition: GlobalContext.h:64
void ignoredSignal(const std::string &signal) const
LuminosityBlockID const & luminosityBlockID() const
Definition: GlobalContext.h:60
void measure_and_store(Resources &store) noexcept
RunNumber_t run() const
const bool enable_dqm_bymodule_
string ranges
Definition: diffTwoXMLs.py:79
unsigned int pathID() const
Definition: PathContext.h:32
void book(dqm::reco::DQMStore::IBooker &, std::string const &name, std::string const &title, PlotRanges const &ranges, unsigned int lumisections, bool byls)
void fill_run(AtomicResources const &)
#define DEFINE_FWK_SERVICE(type)
Definition: ServiceMaker.h:97
static bool is_available()
Definition: memory_usage.cc:84
const bool enable_dqm_byls_
def ls(path, rec=False)
Definition: eostools.py:349
std::vector< PlotsPerProcess > processes_
void postModuleEventAcquire(edm::StreamContext const &, edm::ModuleCallingContext const &)
void postModuleEventDelayedGet(edm::StreamContext const &, edm::ModuleCallingContext const &)
const bool print_event_summary_
virtual void setYTitle(std::string const &title)
LuminosityBlockIndex const & luminosityBlockIndex() const
Definition: StreamContext.h:61
static std::shared_ptr< specific_t > * ptr(void *p)
unsigned long long uint64_t
Definition: Time.h:13
void postModuleStreamBeginLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preModuleStreamEndRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
void postModuleStreamEndRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
part
Definition: HCALResponse.h:20
def load(fileName)
Definition: svgfig.py:547
void printEventHeader(T &out, std::string const &label) const
static uint64_t allocated()
Definition: memory_usage.cc:86
void postModuleStreamBeginRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preSourceEvent(edm::StreamID)
static void retire_thread(void *t)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void preEvent(edm::StreamContext const &)
void postGlobalBeginRun(edm::GlobalContext const &)
void printEventLine(T &out, Resources const &data, std::string const &label) const
void preStreamBeginLumi(edm::StreamContext const &)
ResourcesPerProcess(ProcessCallGraph::ProcessType const &process)
void postSourceEvent(edm::StreamID)
void preModuleStreamBeginLumi(edm::StreamContext const &, edm::ModuleCallingContext const &)
void printPathSummaryHeader(T &out, std::string const &label) const
bool isSubProcess() const
void preStreamEndRun(edm::StreamContext const &)
PlaceInPathContext const * placeInPathContext() const
RunIndex const & runIndex() const
Definition: GlobalContext.h:61
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
void preModuleStreamBeginRun(edm::StreamContext const &, edm::ModuleCallingContext const &)
void printHeader(T &out, std::string const &label) const
void preStreamEndLumi(edm::StreamContext const &)
void measure_and_accumulate(Resources &store) noexcept
ResourcesPerModule & operator+=(ResourcesPerModule const &other)
EventID const & eventID() const
Definition: StreamContext.h:59
void postModuleEventPrefetching(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preModuleGlobalEndLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
ResourcesPerPath operator+(ResourcesPerPath const &other) const
void preGlobalBeginLumi(edm::GlobalContext const &)
AtomicResources & operator+=(AtomicResources const &other)
Resources & operator+=(Resources const &other)
void preModuleEventPrefetching(edm::StreamContext const &, edm::ModuleCallingContext const &)
void preSourceConstruction(edm::ModuleDescription const &)
void preModuleEventAcquire(edm::StreamContext const &, edm::ModuleCallingContext const &)
PathContext const * pathContext() const
void preModuleGlobalEndRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
ProcessType const & processDescription(unsigned int) const
void printTransition(T &out, AtomicResources const &data, std::string const &label) const
void postSourceLumi(edm::LuminosityBlockIndex)
void postModuleGlobalBeginRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
unsigned int value() const
Definition: StreamID.h:43
std::vector< ResourcesPerProcess > processes
Log< level::Warning, false > LogWarning
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
UseScope< MonitorElementData::Scope::RUN > UseRunScope
Definition: DQMStore.h:541
AtomicResources & operator=(AtomicResources const &other)
bool isEndPath() const
Definition: PathContext.h:35
ProcessCallGraph callgraph_
long double T
void postModuleGlobalBeginLumi(edm::GlobalContext const &, edm::ModuleCallingContext const &)
std::string const & moduleLabel() const
void preStreamBeginRun(edm::StreamContext const &)
void preModuleGlobalBeginRun(edm::GlobalContext const &, edm::ModuleCallingContext const &)
RunIndex const & runIndex() const
Definition: StreamContext.h:60
static std::string const source
Definition: EdmProvDump.cc:46
int events
unsigned int concurrent_streams_
bool isLastSubprocess(std::atomic< unsigned int > &check)
Definition: event.py:1
void preallocate(edm::service::SystemBounds const &)
void fill(ProcessCallGraph const &, ResourcesPerJob const &, unsigned int ls)
#define LogDebug(id)
ParentContext const & parent() const
void fill(ProcessCallGraph::PathType const &, ResourcesPerJob const &, ResourcesPerPath const &, unsigned int lumisection)