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  : highlight{groups.size()}, modules{job.size()}, 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  idle.reset();
272  eventsetup.reset();
273  event.reset();
274  for (auto& module : highlight)
275  module.reset();
276  for (auto& module : modules)
277  module.reset();
278  for (auto& process : processes)
279  process.reset();
280  events = 0;
281 }
282 
284  total += other.total;
285  overhead += other.overhead;
286  idle += other.idle;
287  eventsetup += other.eventsetup;
288  event += other.event;
289  assert(highlight.size() == other.highlight.size());
290  for (unsigned int i : boost::irange(0ul, highlight.size()))
291  highlight[i] += other.highlight[i];
292  assert(modules.size() == other.modules.size());
293  for (unsigned int i : boost::irange(0ul, modules.size()))
294  modules[i] += other.modules[i];
295  assert(processes.size() == other.processes.size());
296  for (unsigned int i : boost::irange(0ul, processes.size()))
297  processes[i] += other.processes[i];
298  events += other.events;
299  return *this;
300 }
301 
303  ResourcesPerJob result(*this);
304  result += other;
305  return result;
306 }
307 
308 // per-thread measurements
309 
310 // Measurement
311 
313 
315 #ifdef DEBUG_THREAD_CONCURRENCY
316  id = std::this_thread::get_id();
317 #endif // DEBUG_THREAD_CONCURRENCY
318  time_thread = boost::chrono::thread_clock::now();
320  allocated = memory_usage::allocated();
321  deallocated = memory_usage::deallocated();
322 }
323 
325 #ifdef DEBUG_THREAD_CONCURRENCY
326  assert(std::this_thread::get_id() == id);
327 #endif // DEBUG_THREAD_CONCURRENCY
328  auto new_time_thread = boost::chrono::thread_clock::now();
329  auto new_time_real = boost::chrono::high_resolution_clock::now();
330  auto new_allocated = memory_usage::allocated();
331  auto new_deallocated = memory_usage::deallocated();
332  store.time_thread = new_time_thread - time_thread;
333  store.time_real = new_time_real - time_real;
334  store.allocated = new_allocated - allocated;
335  store.deallocated = new_deallocated - deallocated;
336  time_thread = new_time_thread;
337  time_real = new_time_real;
338  allocated = new_allocated;
339  deallocated = new_deallocated;
340 }
341 
343 #ifdef DEBUG_THREAD_CONCURRENCY
344  assert(std::this_thread::get_id() == id);
345 #endif // DEBUG_THREAD_CONCURRENCY
346  auto new_time_thread = boost::chrono::thread_clock::now();
347  auto new_time_real = boost::chrono::high_resolution_clock::now();
348  auto new_allocated = memory_usage::allocated();
349  auto new_deallocated = memory_usage::deallocated();
350  store.time_thread += new_time_thread - time_thread;
351  store.time_real += new_time_real - time_real;
352  store.allocated += new_allocated - allocated;
353  store.deallocated += new_deallocated - deallocated;
354  time_thread = new_time_thread;
355  time_real = new_time_real;
356  allocated = new_allocated;
357  deallocated = new_deallocated;
358 }
359 
361 #ifdef DEBUG_THREAD_CONCURRENCY
362  assert(std::this_thread::get_id() == id);
363 #endif // DEBUG_THREAD_CONCURRENCY
364  auto new_time_thread = boost::chrono::thread_clock::now();
365  auto new_time_real = boost::chrono::high_resolution_clock::now();
366  auto new_allocated = memory_usage::allocated();
367  auto new_deallocated = memory_usage::deallocated();
368  store.time_thread += boost::chrono::duration_cast<boost::chrono::nanoseconds>(new_time_thread - time_thread).count();
369  store.time_real += boost::chrono::duration_cast<boost::chrono::nanoseconds>(new_time_real - time_real).count();
370  store.allocated += new_allocated - allocated;
371  store.deallocated += new_deallocated - deallocated;
372  time_thread = new_time_thread;
373  time_real = new_time_real;
374  allocated = new_allocated;
375  deallocated = new_deallocated;
376 }
377 
379 
381  std::string const& name,
382  std::string const& title,
383  PlotRanges const& ranges,
384  unsigned int lumisections,
385  bool byls) {
386  int time_bins = (int)std::ceil(ranges.time_range / ranges.time_resolution);
387  int mem_bins = (int)std::ceil(ranges.memory_range / ranges.memory_resolution);
388  std::string y_title_ms = fmt::sprintf("events / %.1f ms", ranges.time_resolution);
389  std::string y_title_kB = fmt::sprintf("events / %.1f kB", ranges.memory_resolution);
390 
391  // MonitorElement::setStatOverflows(kTRUE) includes underflows and overflows in the computation of mean and RMS
392  time_thread_ =
393  booker.book1D(name + " time_thread", title + " processing time (cpu)", time_bins, 0., ranges.time_range);
394  time_thread_->setXTitle("processing time [ms]");
395  time_thread_->setYTitle(y_title_ms);
396  time_thread_->setStatOverflows(kTRUE);
397 
398  time_real_ = booker.book1D(name + " time_real", title + " processing time (real)", time_bins, 0., ranges.time_range);
399  time_real_->setXTitle("processing time [ms]");
400  time_real_->setYTitle(y_title_ms);
401  time_real_->setStatOverflows(kTRUE);
402 
404  allocated_ = booker.book1D(name + " allocated", title + " allocated memory", mem_bins, 0., ranges.memory_range);
405  allocated_->setXTitle("memory [kB]");
406  allocated_->setYTitle(y_title_kB);
407  allocated_->setStatOverflows(kTRUE);
408 
409  deallocated_ =
410  booker.book1D(name + " deallocated", title + " deallocated memory", mem_bins, 0., ranges.memory_range);
411  deallocated_->setXTitle("memory [kB]");
412  deallocated_->setYTitle(y_title_kB);
413  deallocated_->setStatOverflows(kTRUE);
414  }
415 
416  if (not byls)
417  return;
418 
419  time_thread_byls_ = booker.bookProfile(name + " time_thread_byls",
420  title + " processing time (cpu) vs. lumisection",
421  lumisections,
422  0.5,
423  lumisections + 0.5,
424  time_bins,
425  0.,
427  " ");
428  time_thread_byls_->setXTitle("lumisection");
429  time_thread_byls_->setYTitle("processing time [ms]");
430  time_thread_byls_->setStatOverflows(kTRUE);
431 
432  time_real_byls_ = booker.bookProfile(name + " time_real_byls",
433  title + " processing time (real) vs. lumisection",
434  lumisections,
435  0.5,
436  lumisections + 0.5,
437  time_bins,
438  0.,
440  " ");
441  time_real_byls_->setXTitle("lumisection");
442  time_real_byls_->setYTitle("processing time [ms]");
443  time_real_byls_->setStatOverflows(kTRUE);
444 
446  allocated_byls_ = booker.bookProfile(name + " allocated_byls",
447  title + " allocated memory vs. lumisection",
448  lumisections,
449  0.5,
450  lumisections + 0.5,
451  mem_bins,
452  0.,
454  " ");
455  allocated_byls_->setXTitle("lumisection");
456  allocated_byls_->setYTitle("memory [kB]");
457  allocated_byls_->setStatOverflows(kTRUE);
458 
459  deallocated_byls_ = booker.bookProfile(name + " deallocated_byls",
460  title + " deallocated memory vs. lumisection",
461  lumisections,
462  0.5,
463  lumisections + 0.5,
464  mem_bins,
465  0.,
467  " ");
468  deallocated_byls_->setXTitle("lumisection");
469  deallocated_byls_->setYTitle("memory [kB]");
470  deallocated_byls_->setStatOverflows(kTRUE);
471  }
472 }
473 
474 void FastTimerService::PlotsPerElement::fill(Resources const& data, unsigned int lumisection) {
475  if (time_thread_)
476  time_thread_->Fill(ms(data.time_thread));
477 
478  if (time_thread_byls_)
479  time_thread_byls_->Fill(lumisection, ms(data.time_thread));
480 
481  if (time_real_)
482  time_real_->Fill(ms(data.time_real));
483 
484  if (time_real_byls_)
485  time_real_byls_->Fill(lumisection, ms(data.time_real));
486 
487  if (allocated_)
488  allocated_->Fill(kB(data.allocated));
489 
490  if (allocated_byls_)
491  allocated_byls_->Fill(lumisection, kB(data.allocated));
492 
493  if (deallocated_)
494  deallocated_->Fill(kB(data.deallocated));
495 
496  if (deallocated_byls_)
497  deallocated_byls_->Fill(lumisection, kB(data.deallocated));
498 }
499 
500 void FastTimerService::PlotsPerElement::fill(AtomicResources const& data, unsigned int lumisection) {
501  if (time_thread_)
502  time_thread_->Fill(ms(boost::chrono::nanoseconds(data.time_thread.load())));
503 
504  if (time_thread_byls_)
505  time_thread_byls_->Fill(lumisection, ms(boost::chrono::nanoseconds(data.time_thread.load())));
506 
507  if (time_real_)
508  time_real_->Fill(ms(boost::chrono::nanoseconds(data.time_real.load())));
509 
510  if (time_real_byls_)
511  time_real_byls_->Fill(lumisection, ms(boost::chrono::nanoseconds(data.time_real.load())));
512 
513  if (allocated_)
514  allocated_->Fill(kB(data.allocated));
515 
516  if (allocated_byls_)
517  allocated_byls_->Fill(lumisection, kB(data.allocated));
518 
519  if (deallocated_)
520  deallocated_->Fill(kB(data.deallocated));
521 
522  if (deallocated_byls_)
523  deallocated_byls_->Fill(lumisection, kB(data.deallocated));
524 }
525 
527  Resources const& part,
528  unsigned int lumisection) {
529  float total;
530  float fraction;
531 
532  total = ms(data.time_thread);
533  fraction = (total > 0.) ? (ms(part.time_thread) / total) : 0.;
534  if (time_thread_)
535  time_thread_->Fill(total, fraction);
536 
537  if (time_thread_byls_)
538  time_thread_byls_->Fill(lumisection, total, fraction);
539 
540  total = ms(data.time_real);
541  fraction = (total > 0.) ? (ms(part.time_real) / total) : 0.;
542  if (time_real_)
543  time_real_->Fill(total, fraction);
544 
545  if (time_real_byls_)
546  time_real_byls_->Fill(lumisection, total, fraction);
547 
548  total = kB(data.allocated);
549  fraction = (total > 0.) ? (kB(part.allocated) / total) : 0.;
550  if (allocated_)
551  allocated_->Fill(total, fraction);
552 
553  if (allocated_byls_)
554  allocated_byls_->Fill(lumisection, total, fraction);
555 
556  total = kB(data.deallocated);
557  fraction = (total > 0.) ? (kB(part.deallocated) / total) : 0.;
558  if (deallocated_)
559  deallocated_->Fill(total, fraction);
560 
561  if (deallocated_byls_)
562  deallocated_byls_->Fill(lumisection, total, fraction);
563 }
564 
566  std::string const& prefixDir,
567  ProcessCallGraph const& job,
569  PlotRanges const& ranges,
570  unsigned int lumisections,
571  bool byls) {
572  const std::string basedir = booker.pwd();
573  std::string folderName = basedir + "/" + prefixDir + path.name_;
576 
577  total_.book(booker, "path", path.name_, ranges, lumisections, byls);
578 
579  // MonitorElement::setStatOverflows(kTRUE) includes underflows and overflows in the computation of mean and RMS
580  unsigned int bins = path.modules_and_dependencies_.size();
581  module_counter_ = booker.book1DD("module_counter", "module counter", bins + 1, -0.5, bins + 0.5);
582  module_counter_->setYTitle("events");
583  module_counter_->setStatOverflows(kTRUE);
584  module_time_thread_total_ =
585  booker.book1DD("module_time_thread_total", "total module time (cpu)", bins, -0.5, bins - 0.5);
586  module_time_thread_total_->setYTitle("processing time [ms]");
587  module_time_thread_total_->setStatOverflows(kTRUE);
588  module_time_real_total_ =
589  booker.book1DD("module_time_real_total", "total module time (real)", bins, -0.5, bins - 0.5);
590  module_time_real_total_->setYTitle("processing time [ms]");
591  module_time_real_total_->setStatOverflows(kTRUE);
593  module_allocated_total_ =
594  booker.book1DD("module_allocated_total", "total allocated memory", bins, -0.5, bins - 0.5);
595  module_allocated_total_->setYTitle("memory [kB]");
596  module_allocated_total_->setStatOverflows(kTRUE);
597  module_deallocated_total_ =
598  booker.book1DD("module_deallocated_total", "total deallocated memory", bins, -0.5, bins - 0.5);
599  module_deallocated_total_->setYTitle("memory [kB]");
600  module_deallocated_total_->setStatOverflows(kTRUE);
601  }
602  for (unsigned int bin : boost::irange(0u, bins)) {
603  auto const& module = job[path.modules_and_dependencies_[bin]];
604  std::string const& label =
605  module.scheduled_ ? module.module_.moduleLabel() : module.module_.moduleLabel() + " (unscheduled)";
606  module_counter_->setBinLabel(bin + 1, label);
607  module_time_thread_total_->setBinLabel(bin + 1, label);
608  module_time_real_total_->setBinLabel(bin + 1, label);
610  module_allocated_total_->setBinLabel(bin + 1, label);
611  module_deallocated_total_->setBinLabel(bin + 1, label);
612  }
613  }
614  module_counter_->setBinLabel(bins + 1, "");
615 
616  booker.setCurrentFolder(basedir);
617 }
618 
620  ResourcesPerJob const& data,
621  ResourcesPerPath const& path,
622  unsigned int ls) {
623  // fill the total path time
624  total_.fill(path.total, ls);
625 
626  // fill the modules that actually ran and the total time spent in each od them
627  for (unsigned int i = 0; i < path.last; ++i) {
628  auto const& module = data.modules[description.modules_and_dependencies_[i]];
629  if (module_counter_)
630  module_counter_->Fill(i);
631 
632  if (module_time_thread_total_)
633  module_time_thread_total_->Fill(i, ms(module.total.time_thread));
634 
635  if (module_time_real_total_)
636  module_time_real_total_->Fill(i, ms(module.total.time_real));
637 
638  if (module_allocated_total_)
639  module_allocated_total_->Fill(i, kB(module.total.allocated));
640 
641  if (module_deallocated_total_)
642  module_deallocated_total_->Fill(i, kB(module.total.deallocated));
643  }
644  if (module_counter_ and path.status)
645  module_counter_->Fill(path.last);
646 }
647 
649  : event_(), paths_(process.paths_.size()), endpaths_(process.endPaths_.size()) {}
650 
652  ProcessCallGraph const& job,
654  PlotRanges const& event_ranges,
655  PlotRanges const& path_ranges,
656  unsigned int lumisections,
657  bool bypath,
658  bool byls) {
659  const std::string basedir = booker.pwd();
660  event_.book(booker, "process " + process.name_, "process " + process.name_, event_ranges, lumisections, byls);
661  if (bypath) {
662  booker.setCurrentFolder(basedir + "/process " + process.name_ + " paths");
663  for (unsigned int id : boost::irange(0ul, paths_.size())) {
664  paths_[id].book(booker, "path ", job, process.paths_[id], path_ranges, lumisections, byls);
665  }
666  for (unsigned int id : boost::irange(0ul, endpaths_.size())) {
667  endpaths_[id].book(booker, "endpath ", job, process.endPaths_[id], path_ranges, lumisections, byls);
668  }
669  booker.setCurrentFolder(basedir);
670  }
671 }
672 
674  ResourcesPerJob const& data,
676  unsigned int ls) {
677  // fill process event plots
678  event_.fill(process.total, ls);
679 
680  // fill all paths plots
681  for (unsigned int id : boost::irange(0ul, paths_.size()))
682  paths_[id].fill(description.paths_[id], data, process.paths[id], ls);
683 
684  // fill all endpaths plots
685  for (unsigned int id : boost::irange(0ul, endpaths_.size()))
686  endpaths_[id].fill(description.endPaths_[id], data, process.endpaths[id], ls);
687 }
688 
689 FastTimerService::PlotsPerJob::PlotsPerJob(ProcessCallGraph const& job, std::vector<GroupOfModules> const& groups)
690  : highlight_{groups.size()}, modules_{job.size()} {
691  processes_.reserve(job.processes().size());
692  for (auto const& process : job.processes())
693  processes_.emplace_back(process);
694 }
695 
697  ProcessCallGraph const& job,
698  std::vector<GroupOfModules> const& groups,
699  PlotRanges const& event_ranges,
700  PlotRanges const& path_ranges,
701  PlotRanges const& module_ranges,
702  unsigned int lumisections,
703  bool bymodule,
704  bool bypath,
705  bool byls,
706  bool transitions) {
707  const std::string basedir = booker.pwd();
708 
709  // event summary plots
710  event_.book(booker, "event", "Event", event_ranges, lumisections, byls);
711  event_ex_.book(booker, "explicit", "Event (explicit)", event_ranges, lumisections, byls);
712  overhead_.book(booker, "overhead", "Overhead", event_ranges, lumisections, byls);
713  idle_.book(booker, "idle", "Idle", event_ranges, lumisections, byls);
714 
715  modules_[job.source().id()].book(booker, "source", "Source", module_ranges, lumisections, byls);
716 
717  if (transitions) {
718  lumi_.book(booker, "lumi", "LumiSection transitions", event_ranges, lumisections, byls);
719 
720  run_.book(booker, "run", "Run transtions", event_ranges, lumisections, false);
721  }
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, "highlight " + label, "Highlight " + label, event_ranges, lumisections, byls);
727  }
728 
729  // plots per subprocess (event, modules, paths and endpaths)
730  for (unsigned int pid : boost::irange(0ul, job.processes().size())) {
731  auto const& process = job.processDescription(pid);
732  processes_[pid].book(booker, job, process, event_ranges, path_ranges, lumisections, bypath, byls);
733 
734  if (bymodule) {
735  booker.setCurrentFolder(basedir + "/process " + process.name_ + " modules");
736  for (unsigned int id : process.modules_) {
737  std::string const& module_label = job.module(id).moduleLabel();
738  std::string safe_label = module_label;
739  fixForDQM(safe_label);
740  modules_[id].book(booker, safe_label, module_label, module_ranges, lumisections, byls);
741  }
742  booker.setCurrentFolder(basedir);
743  }
744  }
745 }
746 
748  // fill total event plots
749  event_.fill(data.total, ls);
750  event_ex_.fill(data.event, ls);
751  overhead_.fill(data.overhead, ls);
752  idle_.fill(data.idle, ls);
753 
754  // fill highltight plots
755  for (unsigned int group : boost::irange(0ul, highlight_.size()))
756  highlight_[group].fill_fraction(data.total, data.highlight[group], ls);
757 
758  // fill modules plots
759  for (unsigned int id : boost::irange(0ul, modules_.size()))
760  modules_[id].fill(data.modules[id].total, ls);
761 
762  for (unsigned int pid : boost::irange(0ul, processes_.size()))
763  processes_[pid].fill(job.processDescription(pid), data, data.processes[pid], ls);
764 }
765 
767  // fill run transition plots
768  run_.fill(data, 0);
769 }
770 
772  // fill lumisection transition plots
773  lumi_.fill(data, ls);
774 }
775 
777 
779  : // configuration
780  callgraph_(),
781  // job configuration
783  concurrent_runs_(0),
786  print_event_summary_(config.getUntrackedParameter<bool>("printEventSummary")),
787  print_run_summary_(config.getUntrackedParameter<bool>("printRunSummary")),
788  print_job_summary_(config.getUntrackedParameter<bool>("printJobSummary")),
789  // JSON configuration
790  //write_json_per_event_(config.getUntrackedParameter<bool>("writeJSONByEvent")),
791  //write_json_per_ls_(config.getUntrackedParameter<bool>("writeJSONByLumiSection")),
792  //write_json_per_run_(config.getUntrackedParameter<bool>("writeJSONByRun")),
793  write_json_summary_(config.getUntrackedParameter<bool>("writeJSONSummary")),
794  json_filename_(config.getUntrackedParameter<std::string>("jsonFileName")),
795  // DQM configuration
796  enable_dqm_(config.getUntrackedParameter<bool>("enableDQM")),
797  enable_dqm_bymodule_(config.getUntrackedParameter<bool>("enableDQMbyModule")),
798  enable_dqm_bypath_(config.getUntrackedParameter<bool>("enableDQMbyPath")),
799  enable_dqm_byls_(config.getUntrackedParameter<bool>("enableDQMbyLumiSection")),
800  enable_dqm_bynproc_(config.getUntrackedParameter<bool>("enableDQMbyProcesses")),
801  enable_dqm_transitions_(config.getUntrackedParameter<bool>("enableDQMTransitions")),
802  dqm_event_ranges_({config.getUntrackedParameter<double>("dqmTimeRange"), // ms
803  config.getUntrackedParameter<double>("dqmTimeResolution"), // ms
804  config.getUntrackedParameter<double>("dqmMemoryRange"), // kB
805  config.getUntrackedParameter<double>("dqmMemoryResolution")}), // kB
806  dqm_path_ranges_({config.getUntrackedParameter<double>("dqmPathTimeRange"), // ms
807  config.getUntrackedParameter<double>("dqmPathTimeResolution"), // ms
808  config.getUntrackedParameter<double>("dqmPathMemoryRange"), // kB
809  config.getUntrackedParameter<double>("dqmPathMemoryResolution")}), // kB
810  dqm_module_ranges_({config.getUntrackedParameter<double>("dqmModuleTimeRange"), // ms
811  config.getUntrackedParameter<double>("dqmModuleTimeResolution"), // ms
812  config.getUntrackedParameter<double>("dqmModuleMemoryRange"), // kB
813  config.getUntrackedParameter<double>("dqmModuleMemoryResolution")}), // kB
814  dqm_lumisections_range_(config.getUntrackedParameter<unsigned int>("dqmLumiSectionsRange")),
815  dqm_path_(config.getUntrackedParameter<std::string>("dqmPath")),
816  // highlight configuration
817  highlight_module_psets_(config.getUntrackedParameter<std::vector<edm::ParameterSet>>("highlightModules")),
818  highlight_modules_(highlight_module_psets_.size()) // filled in postBeginJob()
819 {
820  // start observing when a thread enters or leaves the TBB global thread arena
821  tbb::task_scheduler_observer::observe();
822 
823  // register EDM call backs
824  registry.watchPreallocate(this, &FastTimerService::preallocate);
825  registry.watchPreBeginJob(this, &FastTimerService::preBeginJob);
826  registry.watchPostBeginJob(this, &FastTimerService::postBeginJob);
827  registry.watchPostEndJob(this, &FastTimerService::postEndJob);
828  registry.watchPreGlobalBeginRun(this, &FastTimerService::preGlobalBeginRun);
829  //registry.watchPostGlobalBeginRun( this, & FastTimerService::postGlobalBeginRun );
830  //registry.watchPreGlobalEndRun( this, & FastTimerService::preGlobalEndRun );
831  registry.watchPostGlobalEndRun(this, &FastTimerService::postGlobalEndRun);
832  registry.watchPreStreamBeginRun(this, &FastTimerService::preStreamBeginRun);
833  //registry.watchPostStreamBeginRun( this, & FastTimerService::postStreamBeginRun );
834  //registry.watchPreStreamEndRun( this, & FastTimerService::preStreamEndRun );
835  registry.watchPostStreamEndRun(this, &FastTimerService::postStreamEndRun);
836  registry.watchPreGlobalBeginLumi(this, &FastTimerService::preGlobalBeginLumi);
837  //registry.watchPostGlobalBeginLumi( this, & FastTimerService::postGlobalBeginLumi );
838  //registry.watchPreGlobalEndLumi( this, & FastTimerService::preGlobalEndLumi );
839  registry.watchPostGlobalEndLumi(this, &FastTimerService::postGlobalEndLumi);
840  registry.watchPreStreamBeginLumi(this, &FastTimerService::preStreamBeginLumi);
841  //registry.watchPostStreamBeginLumi( this, & FastTimerService::postStreamBeginLumi );
842  //registry.watchPreStreamEndLumi( this, & FastTimerService::preStreamEndLumi );
843  registry.watchPostStreamEndLumi(this, &FastTimerService::postStreamEndLumi);
844  registry.watchPreEvent(this, &FastTimerService::preEvent);
845  registry.watchPostEvent(this, &FastTimerService::postEvent);
846  registry.watchPrePathEvent(this, &FastTimerService::prePathEvent);
847  registry.watchPostPathEvent(this, &FastTimerService::postPathEvent);
848  registry.watchPreSourceConstruction(this, &FastTimerService::preSourceConstruction);
849  //registry.watchPostSourceConstruction( this, & FastTimerService::postSourceConstruction);
850  registry.watchPreSourceRun(this, &FastTimerService::preSourceRun);
851  registry.watchPostSourceRun(this, &FastTimerService::postSourceRun);
852  registry.watchPreSourceLumi(this, &FastTimerService::preSourceLumi);
853  registry.watchPostSourceLumi(this, &FastTimerService::postSourceLumi);
854  registry.watchPreSourceEvent(this, &FastTimerService::preSourceEvent);
855  registry.watchPostSourceEvent(this, &FastTimerService::postSourceEvent);
856  //registry.watchPreModuleConstruction( this, & FastTimerService::preModuleConstruction);
857  //registry.watchPostModuleConstruction( this, & FastTimerService::postModuleConstruction);
858  //registry.watchPreModuleBeginJob( this, & FastTimerService::preModuleBeginJob );
859  //registry.watchPostModuleBeginJob( this, & FastTimerService::postModuleBeginJob );
860  //registry.watchPreModuleEndJob( this, & FastTimerService::preModuleEndJob );
861  //registry.watchPostModuleEndJob( this, & FastTimerService::postModuleEndJob );
862  //registry.watchPreModuleBeginStream( this, & FastTimerService::preModuleBeginStream );
863  //registry.watchPostModuleBeginStream( this, & FastTimerService::postModuleBeginStream );
864  //registry.watchPreModuleEndStream( this, & FastTimerService::preModuleEndStream );
865  //registry.watchPostModuleEndStream( this, & FastTimerService::postModuleEndStream );
866  registry.watchPreModuleGlobalBeginRun(this, &FastTimerService::preModuleGlobalBeginRun);
867  registry.watchPostModuleGlobalBeginRun(this, &FastTimerService::postModuleGlobalBeginRun);
868  registry.watchPreModuleGlobalEndRun(this, &FastTimerService::preModuleGlobalEndRun);
869  registry.watchPostModuleGlobalEndRun(this, &FastTimerService::postModuleGlobalEndRun);
870  registry.watchPreModuleGlobalBeginLumi(this, &FastTimerService::preModuleGlobalBeginLumi);
871  registry.watchPostModuleGlobalBeginLumi(this, &FastTimerService::postModuleGlobalBeginLumi);
872  registry.watchPreModuleGlobalEndLumi(this, &FastTimerService::preModuleGlobalEndLumi);
873  registry.watchPostModuleGlobalEndLumi(this, &FastTimerService::postModuleGlobalEndLumi);
874  registry.watchPreModuleStreamBeginRun(this, &FastTimerService::preModuleStreamBeginRun);
875  registry.watchPostModuleStreamBeginRun(this, &FastTimerService::postModuleStreamBeginRun);
876  registry.watchPreModuleStreamEndRun(this, &FastTimerService::preModuleStreamEndRun);
877  registry.watchPostModuleStreamEndRun(this, &FastTimerService::postModuleStreamEndRun);
878  registry.watchPreModuleStreamBeginLumi(this, &FastTimerService::preModuleStreamBeginLumi);
879  registry.watchPostModuleStreamBeginLumi(this, &FastTimerService::postModuleStreamBeginLumi);
880  registry.watchPreModuleStreamEndLumi(this, &FastTimerService::preModuleStreamEndLumi);
881  registry.watchPostModuleStreamEndLumi(this, &FastTimerService::postModuleStreamEndLumi);
882  //registry.watchPreModuleEventPrefetching( this, & FastTimerService::preModuleEventPrefetching );
883  //registry.watchPostModuleEventPrefetching( this, & FastTimerService::postModuleEventPrefetching );
884  registry.watchPreModuleEventAcquire(this, &FastTimerService::preModuleEventAcquire);
885  registry.watchPostModuleEventAcquire(this, &FastTimerService::postModuleEventAcquire);
886  registry.watchPreModuleEvent(this, &FastTimerService::preModuleEvent);
887  registry.watchPostModuleEvent(this, &FastTimerService::postModuleEvent);
888  registry.watchPreModuleEventDelayedGet(this, &FastTimerService::preModuleEventDelayedGet);
889  registry.watchPostModuleEventDelayedGet(this, &FastTimerService::postModuleEventDelayedGet);
890  registry.watchPreEventReadFromSource(this, &FastTimerService::preEventReadFromSource);
891  registry.watchPostEventReadFromSource(this, &FastTimerService::postEventReadFromSource);
892  registry.watchPreESModule(this, &FastTimerService::preESModule);
893  registry.watchPostESModule(this, &FastTimerService::postESModule);
894 }
895 
896 void FastTimerService::ignoredSignal(const std::string& signal) const {
897  LogDebug("FastTimerService") << "The FastTimerService received is currently not monitoring the signal \"" << signal
898  << "\".\n";
899 }
900 
902  // warn about each signal only once per job
903  if (unsupported_signals_.insert(signal).second)
904  edm::LogWarning("FastTimerService") << "The FastTimerService received the unsupported signal \"" << signal
905  << "\".\n"
906  << "Please report how to reproduce the issue to cms-hlt@cern.ch .";
907 }
908 
910  ignoredSignal(__func__);
911 
912  // reset the run counters only during the main process being run
913  if (isFirstSubprocess(gc)) {
914  auto index = gc.runIndex();
915  subprocess_global_run_check_[index] = 0;
916  run_transition_[index].reset();
917  run_summary_[index].reset();
918 
919  // book the DQM plots
920  if (enable_dqm_) {
921  // define a callback to book the MonitorElements
922  auto bookTransactionCallback = [&, this](dqm::reco::DQMStore::IBooker& booker, dqm::reco::DQMStore::IGetter&) {
923  auto scope = dqm::reco::DQMStore::IBooker::UseRunScope(booker);
924  // we should really do this, but only DQMStore is allowed to touch it
925  // We could move to postGlobalBeginRun, then the DQMStore has sure set it up.
926  //booker.setRunLumi(gc.luminosityBlockID());
927  booker.setCurrentFolder(dqm_path_);
928  plots_->book(booker,
929  callgraph_,
930  highlight_modules_,
931  dqm_event_ranges_,
932  dqm_path_ranges_,
933  dqm_module_ranges_,
934  dqm_lumisections_range_,
935  enable_dqm_bymodule_,
936  enable_dqm_bypath_,
937  enable_dqm_byls_,
938  enable_dqm_transitions_);
939  };
940 
941  // book MonitorElements for this stream
942  edm::Service<dqm::legacy::DQMStore>()->meBookerGetter(bookTransactionCallback);
943  }
944  }
945 }
946 
947 void FastTimerService::postGlobalBeginRun(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
948 
949 void FastTimerService::preStreamBeginRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
950 
952  // clean characters that are deemed unsafe for DQM
953  // see the definition of `s_safe` in DQMServices/Core/src/DQMStore.cc
954  static const auto safe_for_dqm = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# "s;
955  for (auto& c : label)
956  if (safe_for_dqm.find(c) == std::string::npos)
957  c = '_';
958 }
959 
961  concurrent_lumis_ = bounds.maxNumberOfConcurrentLuminosityBlocks();
962  concurrent_runs_ = bounds.maxNumberOfConcurrentRuns();
963  concurrent_streams_ = bounds.maxNumberOfStreams();
964  concurrent_threads_ = bounds.maxNumberOfThreads();
965 
966  if (enable_dqm_bynproc_)
967  dqm_path_ += fmt::sprintf(
968  "/Running on %s with %d streams on %d threads", processor_model, concurrent_streams_, concurrent_threads_);
969 
970  // fix the DQM path to avoid invalid characters
971  fixForDQM(dqm_path_);
972 
973  // allocate atomic variables to keep track of the completion of each step, process by process
974  subprocess_event_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_streams_);
975  for (unsigned int i = 0; i < concurrent_streams_; ++i)
976  subprocess_event_check_[i] = 0;
977  subprocess_global_run_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_runs_);
978  for (unsigned int i = 0; i < concurrent_runs_; ++i)
979  subprocess_global_run_check_[i] = 0;
980  subprocess_global_lumi_check_ = std::make_unique<std::atomic<unsigned int>[]>(concurrent_lumis_);
981  for (unsigned int i = 0; i < concurrent_lumis_; ++i)
982  subprocess_global_lumi_check_[i] = 0;
983 
984  // allocate buffers to keep track of the resources spent in the lumi and run transitions
985  lumi_transition_.resize(concurrent_lumis_);
986  run_transition_.resize(concurrent_runs_);
987 }
988 
990  callgraph_.preSourceConstruction(module);
991 }
992 
994  edm::ProcessContext const& context) {
995  callgraph_.preBeginJob(pathsAndConsumes, context);
996 }
997 
999  unsigned int modules = callgraph_.size();
1000 
1001  // module highlights
1002  for (unsigned int group : boost::irange(0ul, highlight_module_psets_.size())) {
1003  // copy and sort for faster search via std::binary_search
1004  auto labels = highlight_module_psets_[group].getUntrackedParameter<std::vector<std::string>>("modules");
1005  std::sort(labels.begin(), labels.end());
1006 
1007  highlight_modules_[group].label = highlight_module_psets_[group].getUntrackedParameter<std::string>("label");
1008  highlight_modules_[group].modules.reserve(labels.size());
1009  // convert the module labels in module ids
1010  for (unsigned int i = 0; i < modules; ++i) {
1011  auto const& label = callgraph_.module(i).moduleLabel();
1012  if (std::binary_search(labels.begin(), labels.end(), label))
1013  highlight_modules_[group].modules.push_back(i);
1014  }
1015  }
1016  highlight_module_psets_.clear();
1017 
1018  // allocate the resource counters for each stream, process, path and module
1019  ResourcesPerJob temp(callgraph_, highlight_modules_);
1020  streams_.resize(concurrent_streams_, temp);
1021  run_summary_.resize(concurrent_runs_, temp);
1022  job_summary_ = temp;
1023 
1024  // check that the DQMStore service is available
1025  if (enable_dqm_ and not edm::Service<dqm::legacy::DQMStore>().isAvailable()) {
1026  // the DQMStore is not available, disable all DQM plots
1027  enable_dqm_ = false;
1028  edm::LogWarning("FastTimerService") << "The DQMStore is not avalable, the DQM plots will not be generated";
1029  }
1030 
1031  // allocate the structures to hold pointers to the DQM plots
1032  if (enable_dqm_) {
1033  plots_ = std::make_unique<PlotsPerJob>(callgraph_, highlight_modules_);
1034  }
1035 }
1036 
1037 void FastTimerService::postStreamBeginRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1038 
1039 void FastTimerService::preStreamEndRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1040 
1041 void FastTimerService::postStreamEndRun(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1042 
1044  ignoredSignal(__func__);
1045 
1046  // reset the lumi counters only during the main process being run
1047  if (isFirstSubprocess(gc)) {
1048  auto index = gc.luminosityBlockIndex();
1049  subprocess_global_lumi_check_[index] = 0;
1050  lumi_transition_[index].reset();
1051  }
1052 }
1053 
1054 void FastTimerService::postGlobalBeginLumi(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
1055 
1056 void FastTimerService::preGlobalEndLumi(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
1057 
1059  ignoredSignal(__func__);
1060 
1061  // handle the summaries only after the last subprocess has run
1062  auto index = gc.luminosityBlockIndex();
1063  bool last = isLastSubprocess(subprocess_global_lumi_check_[index]);
1064  if (not last)
1065  return;
1066 
1067  edm::LogVerbatim out("FastReport");
1068  auto const& label =
1069  fmt::sprintf("run %d, lumisection %d", gc.luminosityBlockID().run(), gc.luminosityBlockID().luminosityBlock());
1070  printTransition(out, lumi_transition_[index], label);
1071 
1072  if (enable_dqm_ and enable_dqm_transitions_) {
1073  plots_->fill_lumi(lumi_transition_[index], gc.luminosityBlockID().luminosityBlock());
1074  }
1075 }
1076 
1077 void FastTimerService::preStreamBeginLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1078 
1079 void FastTimerService::postStreamBeginLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1080 
1081 void FastTimerService::preStreamEndLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1082 
1083 void FastTimerService::postStreamEndLumi(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1084 
1085 void FastTimerService::preGlobalEndRun(edm::GlobalContext const& gc) { ignoredSignal(__func__); }
1086 
1088  ignoredSignal(__func__);
1089 
1090  // handle the summaries only after the last subprocess has run
1091  auto index = gc.runIndex();
1092  bool last = isLastSubprocess(subprocess_global_run_check_[index]);
1093  if (not last)
1094  return;
1095 
1096  edm::LogVerbatim out("FastReport");
1097  auto const& label = fmt::sprintf("run %d", gc.luminosityBlockID().run());
1098  if (print_run_summary_) {
1099  printSummary(out, run_summary_[index], label);
1100  }
1101  printTransition(out, run_transition_[index], label);
1102 
1103  if (enable_dqm_ and enable_dqm_transitions_) {
1104  plots_->fill_run(run_transition_[index]);
1105  }
1106 }
1107 
1108 void FastTimerService::preSourceRun(edm::RunIndex index) { thread().measure_and_accumulate(job_summary_.overhead); }
1109 
1110 void FastTimerService::postSourceRun(edm::RunIndex index) { thread().measure_and_accumulate(run_transition_[index]); }
1111 
1113  thread().measure_and_accumulate(job_summary_.overhead);
1114 }
1115 
1117  thread().measure_and_accumulate(lumi_transition_[index]);
1118 }
1119 
1121  // stop observing to avoid potential race conditions at exit
1122  tbb::task_scheduler_observer::observe(false);
1123  guard_.finalize();
1124  // print the job summaries
1125  if (print_job_summary_) {
1126  edm::LogVerbatim out("FastReport");
1127  printSummary(out, job_summary_, "Job");
1128  }
1129  if (write_json_summary_) {
1130  writeSummaryJSON(job_summary_, json_filename_);
1131  }
1132 }
1133 
1134 template <typename T>
1136  out << "FastReport ";
1137  if (label.size() < 60)
1138  for (unsigned int i = (60 - label.size()) / 2; i > 0; --i)
1139  out << '-';
1140  out << ' ' << label << " Summary ";
1141  if (label.size() < 60)
1142  for (unsigned int i = (59 - label.size()) / 2; i > 0; --i)
1143  out << '-';
1144  out << '\n';
1145 }
1146 
1147 template <typename T>
1149  out << "FastReport CPU time Real time Allocated Deallocated " << label << "\n";
1150  // FastReport ########.# ms ########.# ms +######### kB -######### kB ...
1151 }
1152 
1153 template <typename T>
1155  out << fmt::sprintf("FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1156  ms(data.time_thread),
1157  ms(data.time_real),
1158  +static_cast<int64_t>(kB(data.allocated)),
1159  -static_cast<int64_t>(kB(data.deallocated)),
1160  label);
1161 }
1162 
1163 template <typename T>
1165  out << fmt::sprintf("FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1166  ms(boost::chrono::nanoseconds(data.time_thread.load())),
1167  ms(boost::chrono::nanoseconds(data.time_real.load())),
1168  +static_cast<int64_t>(kB(data.allocated)),
1169  -static_cast<int64_t>(kB(data.deallocated)),
1170  label);
1171 }
1172 
1173 template <typename T>
1175  printHeader(out, "Event");
1176  printEventHeader(out, "Modules");
1177  auto const& source_d = callgraph_.source();
1178  auto const& source = data.modules[source_d.id()];
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 m : proc_d.modules_) {
1185  auto const& module_d = callgraph_.module(m);
1186  auto const& module = data.modules[m];
1187  printEventLine(out, module.total, " " + module_d.moduleLabel());
1188  }
1189  }
1190  printEventLine(out, data.total, "total");
1191  out << '\n';
1192  printEventHeader(out, "Processes and Paths");
1193  printEventLine(out, source.total, source_d.moduleLabel());
1194  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1195  auto const& proc_d = callgraph_.processDescription(i);
1196  auto const& proc = data.processes[i];
1197  printEventLine(out, proc.total, "process " + proc_d.name_);
1198  for (unsigned int p = 0; p < proc.paths.size(); ++p) {
1199  auto const& name = proc_d.paths_[p].name_;
1200  auto const& path = proc.paths[p];
1201  printEventLine(out, path.active, name + " (only scheduled modules)");
1202  printEventLine(out, path.total, name + " (including dependencies)");
1203  }
1204  for (unsigned int p = 0; p < proc.endpaths.size(); ++p) {
1205  auto const& name = proc_d.endPaths_[p].name_;
1206  auto const& path = proc.endpaths[p];
1207  printEventLine(out, path.active, name + " (only scheduled modules)");
1208  printEventLine(out, path.total, name + " (including dependencies)");
1209  }
1210  }
1211  printEventLine(out, data.total, "total");
1212  out << '\n';
1213  for (unsigned int group : boost::irange(0ul, highlight_modules_.size())) {
1214  printEventHeader(out, "Highlighted modules");
1215  for (unsigned int m : highlight_modules_[group].modules) {
1216  auto const& module_d = callgraph_.module(m);
1217  auto const& module = data.modules[m];
1218  printEventLine(out, module.total, " " + module_d.moduleLabel());
1219  }
1220  printEventLine(out, data.highlight[group], highlight_modules_[group].label);
1221  out << '\n';
1222  }
1223 }
1224 
1225 template <typename T>
1226 void FastTimerService::printSummaryHeader(T& out, std::string const& label, bool detailed) const {
1227  // clang-format off
1228  if (detailed)
1229  out << "FastReport CPU time avg. when run Real time avg. when run Alloc. avg. when run Dealloc. avg. when run ";
1230  // FastReport ########.# ms ########.# ms ########.# ms ########.# ms +######### kB +######### kB -######### kB -######### kB ...
1231  else
1232  out << "FastReport CPU time avg. Real time avg. Alloc. avg. Dealloc. avg. ";
1233  // FastReport ########.# ms ########.# ms +######### kB -######### kB ...
1234  out << label << '\n';
1235  // clang-format on
1236 }
1237 
1238 template <typename T>
1240  // clang-format off
1241  out << "FastReport CPU time sched. / depend. Real time sched. / depend. Alloc. sched. / depend. Dealloc. sched. / depend. ";
1242  // FastReport ########.# ms ########.# ms ########.# ms ########.# ms +######### kB +######### kB -######### kB -######### kB ...
1243  out << label << '\n';
1244  // clang-format on
1245 }
1246 
1247 template <typename T>
1249  out << fmt::sprintf(
1250  // clang-format off
1251  "FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1252  // clang-format on
1253  (events ? ms(data.time_thread) / events : 0),
1254  (events ? ms(data.time_real) / events : 0),
1255  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1256  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1257  label);
1258 }
1259 
1260 template <typename T>
1262  T& out, AtomicResources const& data, uint64_t events, uint64_t active, std::string const& label) const {
1263  out << fmt::sprintf(
1264  // clang-format off
1265  "FastReport %10.1f ms %10.1f ms %10.1f ms %10.1f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n",
1266  // clang-format on
1267  (events ? ms(data.time_thread) / events : 0),
1268  (active ? ms(data.time_thread) / active : 0),
1269  (events ? ms(data.time_real) / events : 0),
1270  (active ? ms(data.time_real) / active : 0),
1271  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1272  (active ? +static_cast<int64_t>(kB(data.allocated) / active) : 0),
1273  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1274  (active ? -static_cast<int64_t>(kB(data.deallocated) / active) : 0),
1275  label);
1276 }
1277 
1278 template <typename T>
1280  AtomicResources const& data,
1281  uint64_t events,
1282  std::string const& label) const {
1283  out << fmt::sprintf(
1284  // clang-format off
1285  "FastReport %10.1f ms %10.1f ms %+10d kB %+10d kB %s\n",
1286  // clang-format on
1287  (events ? ms(data.time_thread) / events : 0),
1288  (events ? ms(data.time_real) / events : 0),
1289  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1290  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1291  label);
1292 }
1293 
1294 template <typename T>
1296  T& out, Resources const& data, uint64_t events, uint64_t active, std::string const& label) const {
1297  out << fmt::sprintf(
1298  "FastReport %10.1f ms %10.1f ms %10.1f ms %10.1f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n",
1299  (events ? ms(data.time_thread) / events : 0),
1300  (active ? ms(data.time_thread) / active : 0),
1301  (events ? ms(data.time_real) / events : 0),
1302  (active ? ms(data.time_real) / active : 0),
1303  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1304  (active ? +static_cast<int64_t>(kB(data.allocated) / active) : 0),
1305  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1306  (active ? -static_cast<int64_t>(kB(data.deallocated) / active) : 0),
1307  label);
1308 }
1309 
1310 template <typename T>
1312  T& out, Resources const& data, Resources const& total, uint64_t events, std::string const& label) const {
1313  out << fmt::sprintf(
1314  "FastReport %10.1f ms %10.1f ms %10.1f ms %10.1f ms %+10d kB %+10d kB %+10d kB %+10d kB %s\n",
1315  (events ? ms(data.time_thread) / events : 0),
1316  (events ? ms(total.time_thread) / events : 0),
1317  (events ? ms(data.time_real) / events : 0),
1318  (events ? ms(total.time_real) / events : 0),
1319  (events ? +static_cast<int64_t>(kB(data.allocated) / events) : 0),
1320  (events ? +static_cast<int64_t>(kB(total.allocated) / events) : 0),
1321  (events ? -static_cast<int64_t>(kB(data.deallocated) / events) : 0),
1322  (events ? -static_cast<int64_t>(kB(total.deallocated) / events) : 0),
1323  label);
1324 }
1325 
1326 template <typename T>
1328  printHeader(out, label);
1329  printSummaryHeader(out, "Modules", true);
1330  auto const& source_d = callgraph_.source();
1331  auto const& source = data.modules[source_d.id()];
1332  printSummaryLine(out, source.total, data.events, source.events, source_d.moduleLabel());
1333  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1334  auto const& proc_d = callgraph_.processDescription(i);
1335  auto const& proc = data.processes[i];
1336  printSummaryLine(out, proc.total, data.events, "process " + proc_d.name_);
1337  for (unsigned int m : proc_d.modules_) {
1338  auto const& module_d = callgraph_.module(m);
1339  auto const& module = data.modules[m];
1340  printSummaryLine(out, module.total, data.events, module.events, " " + module_d.moduleLabel());
1341  }
1342  }
1343  printSummaryLine(out, data.total, data.events, "total");
1344  printSummaryLine(out, data.eventsetup, data.events, "eventsetup");
1345  printSummaryLine(out, data.overhead, data.events, "other");
1346  printSummaryLine(out, data.idle, data.events, "idle");
1347  out << '\n';
1348  printPathSummaryHeader(out, "Processes and Paths");
1349  printSummaryLine(out, source.total, data.events, source_d.moduleLabel());
1350  for (unsigned int i = 0; i < callgraph_.processes().size(); ++i) {
1351  auto const& proc_d = callgraph_.processDescription(i);
1352  auto const& proc = data.processes[i];
1353  printSummaryLine(out, proc.total, data.events, "process " + proc_d.name_);
1354  for (unsigned int p = 0; p < proc.paths.size(); ++p) {
1355  auto const& name = proc_d.paths_[p].name_;
1356  auto const& path = proc.paths[p];
1357  printPathSummaryLine(out, path.active, path.total, data.events, " " + name);
1358  }
1359  for (unsigned int p = 0; p < proc.endpaths.size(); ++p) {
1360  auto const& name = proc_d.endPaths_[p].name_;
1361  auto const& path = proc.endpaths[p];
1362  printPathSummaryLine(out, path.active, path.total, data.events, " " + name);
1363  }
1364  }
1365  printSummaryLine(out, data.total, data.events, "total");
1366  printSummaryLine(out, data.eventsetup, data.events, "eventsetup");
1367  printSummaryLine(out, data.overhead, data.events, "other");
1368  printSummaryLine(out, data.idle, data.events, "idle");
1369  out << '\n';
1370  for (unsigned int group : boost::irange(0ul, highlight_modules_.size())) {
1371  printSummaryHeader(out, "Highlighted modules", true);
1372  for (unsigned int m : highlight_modules_[group].modules) {
1373  auto const& module_d = callgraph_.module(m);
1374  auto const& module = data.modules[m];
1375  printSummaryLine(out, module.total, data.events, module.events, module_d.moduleLabel());
1376  }
1377  printSummaryLine(out, data.highlight[group], data.events, highlight_modules_[group].label);
1378  out << '\n';
1379  }
1380 }
1381 
1382 template <typename T>
1384  printEventHeader(out, "Transition");
1385  printEventLine(out, data, label);
1386 }
1387 
1388 template <typename T>
1390  std::string const& label,
1391  unsigned int events,
1392  T const& data) const {
1393  return json{{"type", type},
1394  {"label", label},
1395  {"events", events},
1396  {"time_thread", ms(data.time_thread)},
1397  {"time_real", ms(data.time_real)},
1398  {"mem_alloc", kB(data.allocated)},
1399  {"mem_free", kB(data.deallocated)}};
1400 }
1401 
1403  return encodeToJSON(module.moduleName(), module.moduleLabel(), data.events, data.total);
1404 }
1405 
1407  json j;
1408 
1409  // write a description of the resources
1410  j["resources"] = json::array({json{{"time_real", "real time"}},
1411  json{{"time_thread", "cpu time"}},
1412  json{{"mem_alloc", "allocated memory"}},
1413  json{{"mem_free", "deallocated memory"}}});
1414 
1415  // write the resources used by the job
1416  j["total"] = encodeToJSON("Job",
1417  callgraph_.processDescription(0).name_,
1418  data.events,
1419  data.total + data.eventsetup + data.overhead + data.idle);
1420 
1421  // write the resources used by every module
1422  j["modules"] = json::array();
1423  for (unsigned int i = 0; i < callgraph_.size(); ++i) {
1424  auto const& module = callgraph_.module(i);
1425  auto const& data_m = data.modules[i];
1426  j["modules"].push_back(encodeToJSON(module, data_m));
1427  }
1428 
1429  // add an entry for the non-event transitions, modules, and idle states
1430  j["modules"].push_back(encodeToJSON("other", "other", data.events, data.overhead));
1431  j["modules"].push_back(encodeToJSON("eventsetup", "eventsetup", data.events, data.eventsetup));
1432  j["modules"].push_back(encodeToJSON("idle", "idle", data.events, data.idle));
1433 
1434  std::ofstream out(filename);
1435  out << std::setw(2) << j << std::flush;
1436 }
1437 
1438 // check if this is the first process being signalled
1440  return (not sc.processContext()->isSubProcess());
1441 }
1442 
1444  return (not gc.processContext()->isSubProcess());
1445 }
1446 
1447 // check if this is the last process being signalled
1448 bool FastTimerService::isLastSubprocess(std::atomic<unsigned int>& check) {
1449  // release-acquire semantic guarantees that all writes in this and other threads are visible
1450  // after this operation; full sequentially-consistent ordering is (probably) not needed.
1451  unsigned int old_value = check.fetch_add(1, std::memory_order_acq_rel);
1452  return (old_value == callgraph_.processes().size() - 1);
1453 }
1454 
1455 void FastTimerService::preEvent(edm::StreamContext const& sc) { ignoredSignal(__func__); }
1456 
1458  ignoredSignal(__func__);
1459 
1460  unsigned int pid = callgraph_.processId(*sc.processContext());
1461  unsigned int sid = sc.streamID();
1462  auto& stream = streams_[sid];
1463  auto& process = callgraph_.processDescription(pid);
1464 
1465  // measure the event resources as the sum of all modules' resources
1466  auto& data = stream.processes[pid].total;
1467  for (unsigned int id : process.modules_)
1468  data += stream.modules[id].total;
1469  stream.total += data;
1470 
1471  // handle the summaries and fill the plots only after the last subprocess has run
1472  bool last = isLastSubprocess(subprocess_event_check_[sid]);
1473  if (not last)
1474  return;
1475 
1476  // measure the event resources explicitly
1477  stream.event_measurement.measure_and_store(stream.event);
1478 
1479  // add to the event resources those used by source (which is not part of any process)
1480  unsigned int id = 0;
1481  stream.total += stream.modules[id].total;
1482 
1483  // highlighted modules
1484  for (unsigned int group : boost::irange(0ul, highlight_modules_.size()))
1485  for (unsigned int i : highlight_modules_[group].modules)
1486  stream.highlight[group] += stream.modules[i].total;
1487 
1488  // avoid concurrent access to the summary objects
1489  {
1490  std::lock_guard<std::mutex> guard(summary_mutex_);
1491  job_summary_ += stream;
1492  run_summary_[sc.runIndex()] += stream;
1493  }
1494 
1495  if (print_event_summary_) {
1496  edm::LogVerbatim out("FastReport");
1497  printEvent(out, stream);
1498  }
1499 
1500  if (enable_dqm_) {
1501  plots_->fill(callgraph_, stream, sc.eventID().luminosityBlock());
1502  }
1503 }
1504 
1506  // clear the event counters
1507  auto& stream = streams_[sid];
1508  stream.reset();
1509  ++stream.events;
1510 
1511  subprocess_event_check_[sid] = 0;
1512 
1513  // reuse the same measurement for the Source module and for the explicit begin of the Event
1514  auto& measurement = thread();
1515  measurement.measure_and_accumulate(stream.overhead);
1516  stream.event_measurement = measurement;
1517 }
1518 
1520  edm::ModuleDescription const& md = callgraph_.source();
1521  unsigned int id = md.id();
1522  auto& stream = streams_[sid];
1523  auto& module = stream.modules[id];
1524 
1525  thread().measure_and_store(module.total);
1526  ++stream.modules[id].events;
1527 }
1528 
1530  unsigned int sid = sc.streamID().value();
1531  unsigned int pid = callgraph_.processId(*sc.processContext());
1532  unsigned int id = pc.pathID();
1533  auto& stream = streams_[sid];
1534  auto& data = pc.isEndPath() ? stream.processes[pid].endpaths[id] : stream.processes[pid].paths[id];
1535  data.status = false;
1536  data.last = 0;
1537 }
1538 
1540  edm::PathContext const& pc,
1541  edm::HLTPathStatus const& status) {
1542  unsigned int sid = sc.streamID().value();
1543  unsigned int pid = callgraph_.processId(*sc.processContext());
1544  unsigned int id = pc.pathID();
1545  auto& stream = streams_[sid];
1546  auto& data = pc.isEndPath() ? stream.processes[pid].endpaths[id] : stream.processes[pid].paths[id];
1547 
1548  auto const& path =
1549  pc.isEndPath() ? callgraph_.processDescription(pid).endPaths_[id] : callgraph_.processDescription(pid).paths_[id];
1550  unsigned int index = path.modules_on_path_.empty() ? 0 : status.index() + 1;
1551  data.last = path.modules_on_path_.empty() ? 0 : path.last_dependency_of_module_[status.index()];
1552 
1553  for (unsigned int i = 0; i < index; ++i) {
1554  auto const& module = stream.modules[path.modules_on_path_[i]];
1555  data.active += module.total;
1556  }
1557  for (unsigned int i = 0; i < data.last; ++i) {
1558  auto const& module = stream.modules[path.modules_and_dependencies_[i]];
1559  data.total += module.total;
1560  }
1561 }
1562 
1564  unsigned int sid = sc.streamID().value();
1565  auto& stream = streams_[sid];
1566  thread().measure_and_accumulate(stream.overhead);
1567 }
1568 
1570  edm::ModuleDescription const& md = *mcc.moduleDescription();
1571  unsigned int id = md.id();
1572  unsigned int sid = sc.streamID().value();
1573  auto& stream = streams_[sid];
1574  auto& module = stream.modules[id];
1575 
1576  module.has_acquire = true;
1577  thread().measure_and_store(module.total);
1578 }
1579 
1581  unsigned int sid = sc.streamID().value();
1582  auto& stream = streams_[sid];
1583  thread().measure_and_accumulate(stream.overhead);
1584 }
1585 
1587  edm::ModuleDescription const& md = *mcc.moduleDescription();
1588  unsigned int id = md.id();
1589  unsigned int sid = sc.streamID().value();
1590  auto& stream = streams_[sid];
1591  auto& module = stream.modules[id];
1592 
1593  if (module.has_acquire) {
1594  thread().measure_and_accumulate(module.total);
1595  } else {
1596  thread().measure_and_store(module.total);
1597  }
1598  ++module.events;
1599 }
1600 
1602  unsupportedSignal(__func__);
1603 }
1604 
1606  unsupportedSignal(__func__);
1607 }
1608 
1610  ignoredSignal(__func__);
1611 }
1612 
1614  ignoredSignal(__func__);
1615 }
1616 
1619  auto& stream = streams_[sc.streamID()];
1620  thread().measure_and_accumulate(stream.overhead);
1621  }
1622 }
1623 
1626  edm::ModuleDescription const& md = callgraph_.source();
1627  unsigned int id = md.id();
1628  auto& stream = streams_[sc.streamID()];
1629  auto& module = stream.modules[id];
1630 
1631  thread().measure_and_accumulate(module.total);
1632  }
1633 }
1634 
1636  thread().measure_and_accumulate(job_summary_.overhead);
1637 }
1638 
1640  auto index = gc.runIndex();
1641  thread().measure_and_accumulate(run_transition_[index]);
1642 }
1643 
1645  thread().measure_and_accumulate(job_summary_.overhead);
1646 }
1647 
1649  auto index = gc.runIndex();
1650  thread().measure_and_accumulate(run_transition_[index]);
1651 }
1652 
1654  thread().measure_and_accumulate(job_summary_.overhead);
1655 }
1656 
1658  auto index = gc.luminosityBlockIndex();
1659  thread().measure_and_accumulate(lumi_transition_[index]);
1660 }
1661 
1663  thread().measure_and_accumulate(job_summary_.overhead);
1664 }
1665 
1667  auto index = gc.luminosityBlockIndex();
1668  thread().measure_and_accumulate(lumi_transition_[index]);
1669 }
1670 
1672  thread().measure_and_accumulate(job_summary_.overhead);
1673 }
1674 
1676  auto index = sc.runIndex();
1677  thread().measure_and_accumulate(run_transition_[index]);
1678 }
1679 
1681  thread().measure_and_accumulate(job_summary_.overhead);
1682 }
1683 
1685  auto index = sc.runIndex();
1686  thread().measure_and_accumulate(run_transition_[index]);
1687 }
1688 
1690  thread().measure_and_accumulate(job_summary_.overhead);
1691 }
1692 
1694  auto index = sc.luminosityBlockIndex();
1695  thread().measure_and_accumulate(lumi_transition_[index]);
1696 }
1697 
1699  thread().measure_and_accumulate(job_summary_.overhead);
1700 }
1701 
1703  auto index = sc.luminosityBlockIndex();
1704  thread().measure_and_accumulate(lumi_transition_[index]);
1705 }
1706 
1708  auto top = cc.getTopModuleCallingContext();
1709  if (top->type() == edm::ParentContext::Type::kPlaceInPath) {
1710  //Paths are only used when processing an Event
1711  unsigned int sid = top->parent().placeInPathContext()->pathContext()->streamContext()->streamID().value();
1712  auto& stream = streams_[sid];
1713  thread().measure_and_accumulate(stream.overhead);
1714  }
1715 }
1718  auto top = cc.getTopModuleCallingContext();
1719  if (top->type() == edm::ParentContext::Type::kPlaceInPath) {
1720  unsigned int sid = top->parent().placeInPathContext()->pathContext()->streamContext()->streamID().value();
1721  auto& stream = streams_[sid];
1722  thread().measure_and_accumulate(stream.eventsetup);
1723  }
1724 }
1725 
1727  auto err = ::pthread_key_create(&key_, retire_thread);
1728  if (err) {
1729  throw cms::Exception("FastTimerService") << "ThreadGuard key creation failed: " << ::strerror(err);
1730  }
1731 }
1732 
1733 // If this is a new thread, register it and return true
1735  auto ptr = ::pthread_getspecific(key_);
1736 
1737  if (not ptr) {
1738  auto it = thread_resources_.emplace_back(std::make_shared<specific_t>(r));
1739  auto pp = new std::shared_ptr<specific_t>(*it);
1740  auto err = ::pthread_setspecific(key_, pp);
1741  if (err) {
1742  throw cms::Exception("FastTimerService") << "ThreadGuard pthread_setspecific failed: " << ::strerror(err);
1743  }
1744  return true;
1745  }
1746  return false;
1747 }
1748 
1749 std::shared_ptr<FastTimerService::ThreadGuard::specific_t>* FastTimerService::ThreadGuard::ptr(void* p) {
1750  return static_cast<std::shared_ptr<specific_t>*>(p);
1751 }
1752 
1753 // called when a thread exits
1755  auto ps = ptr(p);
1756  auto expected = true;
1757  if ((*ps)->live_.compare_exchange_strong(expected, false)) {
1758  // account any resources used or freed by the thread before leaving the TBB pool
1759  (*ps)->measurement_.measure_and_accumulate((*ps)->resource_);
1760  }
1761  delete ps;
1762 }
1763 
1764 // finalize all threads that have not retired
1766  for (auto& p : thread_resources_) {
1767  auto expected = true;
1768  if (p->live_.compare_exchange_strong(expected, false)) {
1769  p->measurement_.measure_and_accumulate(p->resource_);
1770  }
1771  }
1772 }
1773 
1775  return (*ptr(::pthread_getspecific(key_)))->measurement_;
1776 }
1777 
1779  // The AtomicResources passed to register_thread are used to account the resources
1780  // used or freed by the thread after the last active measurement and before leaving the TBB pool.
1782  // initialise the measurement point for a thread that has newly joined the TBB pool
1783  thread().measure();
1784  } else {
1785  // An existing thread is re-joining the TBB pool.
1786  // Note: unsure whether the resources used outside of the TBB pool should be
1787  // - not accounted: thread().measure()
1788  // - considered as idle: thread().measure_and_accumulate(job_summary_.idle)
1789  // - considered as other: thread().measure_and_accumulate(job_summary_.overhead)
1791  }
1792 }
1793 
1795  // Account for the resources used or freed by the thread after the last active measurement and before leaving the TBB pool.
1797 }
1798 
1800 
1801 // describe the module's configuration
1804  desc.addUntracked<bool>("printEventSummary", false);
1805  desc.addUntracked<bool>("printRunSummary", true);
1806  desc.addUntracked<bool>("printJobSummary", true);
1807  // JSON configuration
1808  //desc.addUntracked<bool>("writeJSONByEvent", false);
1809  //desc.addUntracked<bool>("writeJSONByLumiSection", false);
1810  //desc.addUntracked<bool>("writeJSONByRun", false);
1811  desc.addUntracked<bool>("writeJSONSummary", false);
1812  desc.addUntracked<std::string>("jsonFileName", "resources.json");
1813  // DQM configuration
1814  desc.addUntracked<bool>("enableDQM", true);
1815  desc.addUntracked<bool>("enableDQMbyModule", false);
1816  desc.addUntracked<bool>("enableDQMbyPath", false);
1817  desc.addUntracked<bool>("enableDQMbyLumiSection", false);
1818  desc.addUntracked<bool>("enableDQMbyProcesses", false);
1819  desc.addUntracked<bool>("enableDQMTransitions", false);
1820  desc.addUntracked<double>("dqmTimeRange", 1000.); // ms
1821  desc.addUntracked<double>("dqmTimeResolution", 5.); // ms
1822  desc.addUntracked<double>("dqmMemoryRange", 1000000.); // kB
1823  desc.addUntracked<double>("dqmMemoryResolution", 5000.); // kB
1824  desc.addUntracked<double>("dqmPathTimeRange", 100.); // ms
1825  desc.addUntracked<double>("dqmPathTimeResolution", 0.5); // ms
1826  desc.addUntracked<double>("dqmPathMemoryRange", 1000000.); // kB
1827  desc.addUntracked<double>("dqmPathMemoryResolution", 5000.); // kB
1828  desc.addUntracked<double>("dqmModuleTimeRange", 40.); // ms
1829  desc.addUntracked<double>("dqmModuleTimeResolution", 0.2); // ms
1830  desc.addUntracked<double>("dqmModuleMemoryRange", 100000.); // kB
1831  desc.addUntracked<double>("dqmModuleMemoryResolution", 500.); // kB
1832  desc.addUntracked<unsigned>("dqmLumiSectionsRange", 2500); // ~ 16 hours
1833  desc.addUntracked<std::string>("dqmPath", "HLT/TimerService");
1834 
1835  edm::ParameterSetDescription highlightModulesDescription;
1836  highlightModulesDescription.addUntracked<std::vector<std::string>>("modules", {});
1837  highlightModulesDescription.addUntracked<std::string>("label", "producers");
1838  desc.addVPSetUntracked("highlightModules", highlightModulesDescription, {});
1839 
1840  // # OBSOLETE - these parameters are ignored, they are left only not to break old configurations
1841  // they will not be printed in the generated cfi.py file
1842  desc.addOptionalNode(edm::ParameterDescription<bool>("useRealTimeClock", true, false), false)
1843  ->setComment("This parameter is obsolete and will be ignored.");
1844  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingPaths", true, false), false)
1845  ->setComment("This parameter is obsolete and will be ignored.");
1846  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingModules", true, false), false)
1847  ->setComment("This parameter is obsolete and will be ignored.");
1848  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingExclusive", false, false), false)
1849  ->setComment("This parameter is obsolete and will be ignored.");
1850  desc.addOptionalNode(edm::ParameterDescription<bool>("enableTimingSummary", false, false), false)
1851  ->setComment("This parameter is obsolete and will be ignored.");
1852  desc.addOptionalNode(edm::ParameterDescription<bool>("skipFirstPath", false, false), false)
1853  ->setComment("This parameter is obsolete and will be ignored.");
1854  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathActive", false, false), false)
1855  ->setComment("This parameter is obsolete and will be ignored.");
1856  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathTotal", true, false), false)
1857  ->setComment("This parameter is obsolete and will be ignored.");
1858  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathOverhead", false, false), false)
1859  ->setComment("This parameter is obsolete and will be ignored.");
1860  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathDetails", false, false), false)
1861  ->setComment("This parameter is obsolete and will be ignored.");
1862  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathCounters", true, false), false)
1863  ->setComment("This parameter is obsolete and will be ignored.");
1864  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyPathExclusive", false, false), false)
1865  ->setComment("This parameter is obsolete and will be ignored.");
1866  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMbyModuleType", false, false), false)
1867  ->setComment("This parameter is obsolete and will be ignored.");
1868  desc.addOptionalNode(edm::ParameterDescription<bool>("enableDQMSummary", false, false), false)
1869  ->setComment("This parameter is obsolete and will be ignored.");
1870 
1871  descriptions.add("FastTimerService", desc);
1872 }
1873 
1874 // 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:36
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)
ResourcesPerJob job_summary_
PlotsPerJob(ProcessCallGraph const &job, std::vector< GroupOfModules > const &groups)
nlohmann::json json
PlotsPerProcess(ProcessCallGraph::ProcessType const &)
void preGlobalEndLumi(edm::GlobalContext const &)
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
edm::ModuleDescription const & source() const
virtual std::string pwd()
Definition: DQMStore.cc:20
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)
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:55
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:64
const bool enable_dqm_transitions_
LuminosityBlockIndex const & luminosityBlockIndex() const
Definition: GlobalContext.h:64
void printSummaryHeader(T &out, std::string const &label, bool detailed) const
ProcessContext const * processContext() const
Definition: GlobalContext.h:66
void ignoredSignal(const std::string &signal) const
LuminosityBlockID const & luminosityBlockID() const
Definition: GlobalContext.h:62
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
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:62
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 &)
RunIndex const & runIndex() const
Definition: GlobalContext.h:63
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:80
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:60
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 &)
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
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:61
static std::string const source
Definition: EdmProvDump.cc:49
int events
static void fixForDQM(std::string &label)
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)
#define LogDebug(id)
void fill(ProcessCallGraph::PathType const &, ResourcesPerJob const &, ResourcesPerPath const &, unsigned int lumisection)