CMS 3D CMS Logo

StallMonitor.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FWCore/Services
4 // Class : StallMonitor
5 //
6 // Implementation:
7 //
8 // Original Author: Kyle Knoepfel
9 //
10 
30 #include "oneapi/tbb/concurrent_unordered_map.h"
31 
32 #include <atomic>
33 #include <chrono>
34 #include <iomanip>
35 #include <iostream>
36 #include <sstream>
37 
38 namespace {
39 
40  using duration_t = std::chrono::microseconds;
41  using clock_t = std::chrono::steady_clock;
42  auto now = clock_t::now;
43 
44  inline auto stream_id(edm::StreamContext const& cs) { return cs.streamID().value(); }
45 
46  inline auto module_id(edm::ModuleCallingContext const& mcc) { return mcc.moduleDescription()->id(); }
47 
48  inline auto module_id(edm::ESModuleCallingContext const& mcc) { return mcc.componentDescription()->id_; }
49 
50  //===============================================================
51  class StallStatistics {
52  public:
53  // c'tor receiving 'std::string const&' type not provided since we
54  // must be able to call (e.g.) std::vector<StallStatistics>(20),
55  // for which a default label is not sensible in this context.
56  StallStatistics() = default;
57 
58  std::string const& label() const { return label_; }
59  unsigned numberOfStalls() const { return stallCounter_; }
60 
61  using rep_t = duration_t::rep;
62 
63  duration_t totalStalledTime() const { return duration_t{totalTime_.load()}; }
64  duration_t maxStalledTime() const { return duration_t{maxTime_.load()}; }
65 
66  // Modifiers
67  void setLabel(std::string const& label) { label_ = label; }
68 
69  void update(duration_t const ms) {
70  ++stallCounter_;
71  auto const thisTime = ms.count();
72  totalTime_ += thisTime;
73  rep_t max{maxTime_};
74  while (thisTime > max && !maxTime_.compare_exchange_strong(max, thisTime))
75  ;
76  }
77 
78  private:
79  std::string label_{};
80  std::atomic<unsigned> stallCounter_{};
81  std::atomic<rep_t> totalTime_{};
82  std::atomic<rep_t> maxTime_{};
83  };
84 
85  //===============================================================
86  // Message-assembly utilities
87  template <typename T>
88  std::enable_if_t<std::is_integral<T>::value> concatenate(std::ostream& os, T const t) {
89  os << ' ' << t;
90  }
91 
92  template <typename H, typename... T>
93  std::enable_if_t<std::is_integral<H>::value> concatenate(std::ostream& os, H const h, T const... t) {
94  os << ' ' << h;
95  concatenate(os, t...);
96  }
97 
98  enum class step : char {
99  preSourceEvent = 'S',
100  postSourceEvent = 's',
101  preEvent = 'E',
102  postModuleEventPrefetching = 'p',
103  preModuleEventAcquire = 'A',
104  postModuleEventAcquire = 'a',
105  preModuleEvent = 'M',
106  preEventReadFromSource = 'R',
107  postEventReadFromSource = 'r',
108  postModuleEvent = 'm',
109  postEvent = 'e',
110  postESModulePrefetching = 'q',
111  preESModule = 'N',
112  postESModule = 'n'
113  };
114 
115  enum class Phase : short {
116  globalEndRun = -4,
117  streamEndRun = -3,
118  globalEndLumi = -2,
119  streamEndLumi = -1,
120  Event = 0,
121  streamBeginLumi = 1,
122  globalBeginLumi = 2,
123  streamBeginRun = 3,
124  globalBeginRun = 4,
125  eventSetupCall = 5
126  };
127 
128  std::ostream& operator<<(std::ostream& os, step const s) {
129  os << static_cast<std::underlying_type_t<step>>(s);
130  return os;
131  }
132 
133  std::ostream& operator<<(std::ostream& os, Phase const s) {
134  os << static_cast<std::underlying_type_t<Phase>>(s);
135  return os;
136  }
137 
138  template <step S, typename... ARGS>
139  std::string assembleMessage(ARGS const... args) {
140  std::ostringstream oss;
141  oss << S;
142  concatenate(oss, args...);
143  oss << '\n';
144  return oss.str();
145  }
146 
147  Phase toTransitionImpl(edm::StreamContext const& iContext) {
148  using namespace edm;
149  switch (iContext.transition()) {
150  case StreamContext::Transition::kBeginRun:
151  return Phase::streamBeginRun;
152  case StreamContext::Transition::kBeginLuminosityBlock:
153  return Phase::streamBeginLumi;
154  case StreamContext::Transition::kEvent:
155  return Phase::Event;
156  case StreamContext::Transition::kEndLuminosityBlock:
157  return Phase::streamEndLumi;
158  case StreamContext::Transition::kEndRun:
159  return Phase::streamEndRun;
160  default:
161  break;
162  }
163  assert(false);
164  return Phase::Event;
165  }
166 
167  auto toTransition(edm::StreamContext const& iContext) -> std::underlying_type_t<Phase> {
168  return static_cast<std::underlying_type_t<Phase>>(toTransitionImpl(iContext));
169  }
170 
171  Phase toTransitionImpl(edm::GlobalContext const& iContext) {
172  using namespace edm;
173  switch (iContext.transition()) {
174  case GlobalContext::Transition::kBeginRun:
175  return Phase::globalBeginRun;
176  case GlobalContext::Transition::kBeginLuminosityBlock:
177  return Phase::globalBeginLumi;
178  case GlobalContext::Transition::kEndLuminosityBlock:
179  return Phase::globalEndLumi;
180  case GlobalContext::Transition::kWriteLuminosityBlock:
181  return Phase::globalEndLumi;
182  case GlobalContext::Transition::kEndRun:
183  return Phase::globalEndRun;
184  case GlobalContext::Transition::kWriteRun:
185  return Phase::globalEndRun;
186  default:
187  break;
188  }
189  assert(false);
190  return Phase::Event;
191  }
192  auto toTransition(edm::GlobalContext const& iContext) -> std::underlying_type_t<Phase> {
193  return static_cast<std::underlying_type_t<Phase>>(toTransitionImpl(iContext));
194  }
195 
196 } // namespace
197 
198 namespace edm {
199  namespace service {
200 
201  class StallMonitor {
202  public:
204  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
205 
206  private:
207  void preModuleConstruction(edm::ModuleDescription const&);
208  void preModuleDestruction(edm::ModuleDescription const&);
209  void postBeginJob();
210  void preSourceEvent(StreamID);
211  void postSourceEvent(StreamID);
212  void preEvent(StreamContext const&);
213  void preModuleEventAcquire(StreamContext const&, ModuleCallingContext const&);
214  void postModuleEventAcquire(StreamContext const&, ModuleCallingContext const&);
215  void preModuleEvent(StreamContext const&, ModuleCallingContext const&);
216  void postModuleEventPrefetching(StreamContext const&, ModuleCallingContext const&);
217  void preEventReadFromSource(StreamContext const&, ModuleCallingContext const&);
218  void postEventReadFromSource(StreamContext const&, ModuleCallingContext const&);
219  void postModuleEvent(StreamContext const&, ModuleCallingContext const&);
220  void postEvent(StreamContext const&);
221  void preModuleStreamTransition(StreamContext const&, ModuleCallingContext const&);
222  void postModuleStreamTransition(StreamContext const&, ModuleCallingContext const&);
223  void preModuleGlobalTransition(GlobalContext const&, ModuleCallingContext const&);
224  void postModuleGlobalTransition(GlobalContext const&, ModuleCallingContext const&);
225  void postEndJob();
226 
228  bool const validFile_; // Separate data member from file to improve efficiency.
229  duration_t const stallThreshold_;
230  decltype(now()) beginTime_{};
231 
232  // There can be multiple modules per stream. Therefore, we need
233  // the combination of StreamID and ModuleID to correctly track
234  // stalling information. We use oneapi::tbb::concurrent_unordered_map
235  // for this purpose.
236  using StreamID_value = decltype(std::declval<StreamID>().value());
237  using ModuleID = decltype(std::declval<ModuleDescription>().id());
238  oneapi::tbb::concurrent_unordered_map<std::pair<StreamID_value, ModuleID>,
239  std::pair<decltype(beginTime_), bool>,
241  stallStart_{};
242 
243  std::vector<std::string> moduleLabels_{};
244  std::vector<StallStatistics> moduleStats_{};
245  std::vector<std::string> esModuleLabels_{};
246  unsigned int numStreams_;
247  };
248 
249  } // namespace service
250 
251 } // namespace edm
252 
253 namespace {
254  constexpr char const* const filename_default{""};
255  constexpr double threshold_default{0.1}; //default threashold in seconds
256  std::string const space{" "};
257 } // namespace
258 
260 using namespace std::chrono;
261 
262 StallMonitor::StallMonitor(ParameterSet const& iPS, ActivityRegistry& iRegistry)
263  : file_{iPS.getUntrackedParameter<std::string>("fileName", filename_default)},
264  validFile_{file_},
265  stallThreshold_{
266  std::chrono::round<duration_t>(duration<double>(iPS.getUntrackedParameter<double>("stallThreshold")))} {
267  iRegistry.watchPreModuleConstruction(this, &StallMonitor::preModuleConstruction);
268  iRegistry.watchPreModuleDestruction(this, &StallMonitor::preModuleDestruction);
269  iRegistry.watchPostBeginJob(this, &StallMonitor::postBeginJob);
270  iRegistry.watchPostModuleEventPrefetching(this, &StallMonitor::postModuleEventPrefetching);
271  iRegistry.watchPreModuleEventAcquire(this, &StallMonitor::preModuleEventAcquire);
272  iRegistry.watchPreModuleEvent(this, &StallMonitor::preModuleEvent);
273  iRegistry.watchPostEndJob(this, &StallMonitor::postEndJob);
274 
275  if (validFile_) {
276  // Only enable the following callbacks if writing to a file.
277  iRegistry.watchPreSourceEvent(this, &StallMonitor::preSourceEvent);
278  iRegistry.watchPostSourceEvent(this, &StallMonitor::postSourceEvent);
279  iRegistry.watchPreEvent(this, &StallMonitor::preEvent);
280  iRegistry.watchPostModuleEventAcquire(this, &StallMonitor::postModuleEventAcquire);
281  iRegistry.watchPreEventReadFromSource(this, &StallMonitor::preEventReadFromSource);
282  iRegistry.watchPostEventReadFromSource(this, &StallMonitor::postEventReadFromSource);
283  iRegistry.watchPostModuleEvent(this, &StallMonitor::postModuleEvent);
284  iRegistry.watchPostEvent(this, &StallMonitor::postEvent);
285 
286  iRegistry.watchPreModuleStreamBeginRun(this, &StallMonitor::preModuleStreamTransition);
287  iRegistry.watchPostModuleStreamBeginRun(this, &StallMonitor::postModuleStreamTransition);
288  iRegistry.watchPreModuleStreamEndRun(this, &StallMonitor::preModuleStreamTransition);
289  iRegistry.watchPostModuleStreamEndRun(this, &StallMonitor::postModuleStreamTransition);
290 
291  iRegistry.watchPreModuleStreamBeginLumi(this, &StallMonitor::preModuleStreamTransition);
292  iRegistry.watchPostModuleStreamBeginLumi(this, &StallMonitor::postModuleStreamTransition);
293  iRegistry.watchPreModuleStreamEndLumi(this, &StallMonitor::preModuleStreamTransition);
294  iRegistry.watchPostModuleStreamEndLumi(this, &StallMonitor::postModuleStreamTransition);
295 
296  iRegistry.watchPreModuleGlobalBeginRun(this, &StallMonitor::preModuleGlobalTransition);
297  iRegistry.watchPostModuleGlobalBeginRun(this, &StallMonitor::postModuleGlobalTransition);
298  iRegistry.watchPreModuleGlobalEndRun(this, &StallMonitor::preModuleGlobalTransition);
299  iRegistry.watchPostModuleGlobalEndRun(this, &StallMonitor::postModuleGlobalTransition);
300  iRegistry.watchPreModuleWriteRun(this, &StallMonitor::preModuleGlobalTransition);
301  iRegistry.watchPostModuleWriteRun(this, &StallMonitor::postModuleGlobalTransition);
302 
303  iRegistry.watchPreModuleGlobalBeginLumi(this, &StallMonitor::preModuleGlobalTransition);
304  iRegistry.watchPostModuleGlobalBeginLumi(this, &StallMonitor::postModuleGlobalTransition);
305  iRegistry.watchPreModuleGlobalEndLumi(this, &StallMonitor::preModuleGlobalTransition);
306  iRegistry.watchPostModuleGlobalEndLumi(this, &StallMonitor::postModuleGlobalTransition);
307  iRegistry.watchPreModuleWriteLumi(this, &StallMonitor::preModuleGlobalTransition);
308  iRegistry.watchPostModuleWriteLumi(this, &StallMonitor::postModuleGlobalTransition);
309 
310  iRegistry.postESModuleRegistrationSignal_.connect([this](auto const& iDescription) {
311  if (esModuleLabels_.size() <= iDescription.id_) {
312  esModuleLabels_.resize(iDescription.id_ + 1);
313  }
314  if (not iDescription.label_.empty()) {
315  esModuleLabels_[iDescription.id_] = iDescription.label_;
316  } else {
317  esModuleLabels_[iDescription.id_] = iDescription.type_;
318  }
319  });
320 
321  iRegistry.preESModuleSignal_.connect([this](auto const&, auto const& context) {
322  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
323  auto msg = assembleMessage<step::preESModule>(
324  numStreams_, module_id(context), std::underlying_type_t<Phase>(Phase::eventSetupCall), t);
325  file_.write(std::move(msg));
326  });
327  iRegistry.postESModuleSignal_.connect([this](auto const&, auto const& context) {
328  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
329  auto msg = assembleMessage<step::postESModule>(
330  numStreams_, module_id(context), std::underlying_type_t<Phase>(Phase::eventSetupCall), t);
331  file_.write(std::move(msg));
332  });
333 
334  iRegistry.preallocateSignal_.connect(
335  [this](service::SystemBounds const& iBounds) { numStreams_ = iBounds.maxNumberOfStreams(); });
336 
337  std::ostringstream oss;
338  oss << "# Transition Symbol\n";
339  oss << "#----------------- ------\n";
340  oss << "# eventSetupCall " << Phase::eventSetupCall << "\n"
341  << "# globalBeginRun " << Phase::globalBeginRun << "\n"
342  << "# streamBeginRun " << Phase::streamBeginRun << "\n"
343  << "# globalBeginLumi " << Phase::globalBeginLumi << "\n"
344  << "# streamBeginLumi " << Phase::streamBeginLumi << "\n"
345  << "# Event " << Phase::Event << "\n"
346  << "# streamEndLumi " << Phase::streamEndLumi << "\n"
347  << "# globalEndLumi " << Phase::globalEndLumi << "\n"
348  << "# streamEndRun " << Phase::streamEndRun << "\n"
349  << "# globalEndRun " << Phase::globalEndRun << "\n";
350  oss << "# Step Symbol Entries\n"
351  << "# -------------------------- ------ ------------------------------------------\n"
352  << "# preSourceEvent " << step::preSourceEvent << " <Stream ID> <Time since beginJob (ms)>\n"
353  << "# postSourceEvent " << step::postSourceEvent << " <Stream ID> <Time since beginJob (ms)>\n"
354  << "# preEvent " << step::preEvent
355  << " <Stream ID> <Run#> <LumiBlock#> <Event#> <Time since beginJob (ms)>\n"
356  << "# postModuleEventPrefetching " << step::postModuleEventPrefetching
357  << " <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
358  << "# preModuleEventAcquire " << step::preModuleEventAcquire
359  << " <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
360  << "# postModuleEventAcquire " << step::postModuleEventAcquire
361  << " <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
362  << "# preModuleTransition " << step::preModuleEvent
363  << " <Stream ID> <Module ID> <Transition type> <Time since beginJob (ms)>\n"
364  << "# preEventReadFromSource " << step::preEventReadFromSource
365  << " <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
366  << "# postEventReadFromSource " << step::postEventReadFromSource
367  << " <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
368  << "# postModuleTransition " << step::postModuleEvent
369  << " <Stream ID> <Module ID> <Transition type> <Time since beginJob (ms)>\n"
370  << "# postEvent " << step::postEvent
371  << " <Stream ID> <Run#> <LumiBlock#> <Event#> <Time since beginJob (ms)>\n"
372  << "# postESModulePrefetching " << step::postESModulePrefetching
373  << " <Stream ID> <ESModule ID> <Transition type> <Time since beginJob (ms)>\n"
374  << "# preESModuleTransition " << step::preESModule
375  << " <StreamID> <ESModule ID> <TransitionType> <Time since beginJob (ms)>\n"
376  << "# postESModuleTransition " << step::postESModule
377  << " <StreamID> <ESModule ID> <TransitionType> <Time since beginJob (ms)>\n";
378  file_.write(oss.str());
379  }
380 }
381 
384  desc.addUntracked<std::string>("fileName", filename_default)
385  ->setComment(
386  "Name of file to which detailed timing information should be written.\n"
387  "An empty filename argument (the default) indicates that no extra\n"
388  "information will be written to a dedicated file, but only the summary\n"
389  "including stalling-modules information will be logged.");
390  desc.addUntracked<double>("stallThreshold", threshold_default)
391  ->setComment(
392  "Threshold (in seconds) used to classify modules as stalled.\n"
393  "Microsecond granularity allowed.");
394  descriptions.add("StallMonitor", desc);
395  descriptions.setComment(
396  "This service keeps track of various times in event-processing to determine which modules are stalling.");
397 }
398 
400  // Module labels are dense, so if the module id is greater than the
401  // size of moduleLabels_, grow the vector to the correct index and
402  // assign the last entry to the desired label. Note that with the
403  // current implementation, there is no module with ID '0'. In
404  // principle, the module-information vectors are therefore each one
405  // entry too large. However, since removing the entry at the front
406  // makes for awkward indexing later on, and since the sizes of these
407  // extra entries are on the order of bytes, we will leave them in
408  // and skip over them later when printing out summaries. The
409  // extraneous entries can be identified by their module labels being
410  // empty.
411  auto const mid = md.id();
412  if (mid < moduleLabels_.size()) {
413  moduleLabels_[mid] = md.moduleLabel();
414  } else {
415  moduleLabels_.resize(mid + 1);
416  moduleLabels_.back() = md.moduleLabel();
417  }
418 }
419 
421  // Reset the module label back if the module is deleted before
422  // beginJob() so that the entry is ignored in the summary printouts.
423  moduleLabels_[md.id()] = "";
424 }
425 
427  // Since a (push,emplace)_back cannot be called for a vector of a
428  // type containing atomics (like 'StallStatistics')--i.e. atomics
429  // have no copy/move-assignment operators, we must specify the size
430  // of the vector at construction time.
431  moduleStats_ = std::vector<StallStatistics>(moduleLabels_.size());
432  for (std::size_t i{}; i < moduleStats_.size(); ++i) {
433  moduleStats_[i].setLabel(moduleLabels_[i]);
434  }
435 
436  if (validFile_) {
437  {
438  std::size_t const width{std::to_string(moduleLabels_.size()).size()};
439  OStreamColumn col0{"Module ID", width};
440  std::string const lastCol{"Module label"};
441 
442  std::ostringstream oss;
443  oss << "\n# " << col0 << space << lastCol << '\n';
444  oss << "# " << std::string(col0.width() + space.size() + lastCol.size(), '-') << '\n';
445 
446  for (std::size_t i{}; i < moduleLabels_.size(); ++i) {
447  auto const& label = moduleLabels_[i];
448  if (label.empty())
449  continue; // See comment in filling of moduleLabels_;
450  oss << "#M " << std::setw(width) << std::left << col0(i) << space << std::left << moduleLabels_[i] << '\n';
451  }
452  oss << '\n';
453  file_.write(oss.str());
454  }
455  {
456  std::size_t const width{std::to_string(esModuleLabels_.size()).size()};
457  OStreamColumn col0{"ESModule ID", width};
458  std::string const lastCol{"ESModule label"};
459 
460  std::ostringstream oss;
461  oss << "\n# " << col0 << space << lastCol << '\n';
462  oss << "# " << std::string(col0.width() + space.size() + lastCol.size(), '-') << '\n';
463 
464  for (std::size_t i{}; i < esModuleLabels_.size(); ++i) {
465  auto const& label = esModuleLabels_[i];
466  if (label.empty())
467  continue; // See comment in filling of moduleLabels_;
468  oss << "#N " << std::setw(width) << std::left << col0(i) << space << std::left << esModuleLabels_[i] << '\n';
469  }
470  oss << '\n';
471  file_.write(oss.str());
472  }
473  }
474  // Don't need the labels anymore--info. is now part of the
475  // module-statistics objects.
476  decltype(moduleLabels_)().swap(moduleLabels_);
477  decltype(esModuleLabels_)().swap(esModuleLabels_);
478 
479  beginTime_ = now();
480 }
481 
483  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
484  auto msg = assembleMessage<step::preSourceEvent>(sid.value(), t);
486 }
487 
489  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
490  auto msg = assembleMessage<step::postSourceEvent>(sid.value(), t);
492 }
493 
495  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
496  auto const& eid = sc.eventID();
497  auto msg = assembleMessage<step::preEvent>(stream_id(sc), eid.run(), eid.luminosityBlock(), eid.event(), t);
499 }
500 
502  auto const sid = stream_id(sc);
503  auto const mid = module_id(mcc);
504  auto start = stallStart_[std::make_pair(sid, mid)] = std::make_pair(now(), false);
505 
506  if (validFile_) {
507  auto const t = duration_cast<duration_t>(start.first - beginTime_).count();
508  auto msg = assembleMessage<step::postModuleEventPrefetching>(sid, mid, t);
510  }
511 }
512 
514  auto const preModEventAcquire = now();
515  auto const sid = stream_id(sc);
516  auto const mid = module_id(mcc);
517  auto& start = stallStart_[std::make_pair(sid, mid)];
518  auto startT = start.first.time_since_epoch();
519  start.second = true; // record so the preModuleEvent knows that acquire was called
520  if (validFile_) {
521  auto t = duration_cast<duration_t>(preModEventAcquire - beginTime_).count();
522  auto msg = assembleMessage<step::preModuleEventAcquire>(sid, mid, t);
524  }
525  // Check for stalls if prefetch was called
526  if (duration_t::duration::zero() != startT) {
527  auto const preFetch_to_preModEventAcquire = duration_cast<duration_t>(preModEventAcquire - start.first);
528  if (preFetch_to_preModEventAcquire < stallThreshold_)
529  return;
530  moduleStats_[mid].update(preFetch_to_preModEventAcquire);
531  }
532 }
533 
535  auto const postModEventAcquire = duration_cast<duration_t>(now() - beginTime_).count();
536  auto msg = assembleMessage<step::postModuleEventAcquire>(stream_id(sc), module_id(mcc), postModEventAcquire);
538 }
539 
541  auto const preModEvent = now();
542  auto const sid = stream_id(sc);
543  auto const mid = module_id(mcc);
544  auto const& start = stallStart_[std::make_pair(sid, mid)];
545  auto startT = start.first.time_since_epoch();
546  if (validFile_) {
547  auto t = duration_cast<duration_t>(preModEvent - beginTime_).count();
548  auto msg =
549  assembleMessage<step::preModuleEvent>(sid, mid, static_cast<std::underlying_type_t<Phase>>(Phase::Event), t);
551  }
552  // Check for stalls if prefetch was called and we did not already check before acquire
553  if (duration_t::duration::zero() != startT && !start.second) {
554  auto const preFetch_to_preModEvent = duration_cast<duration_t>(preModEvent - start.first);
555  if (preFetch_to_preModEvent < stallThreshold_)
556  return;
557  moduleStats_[mid].update(preFetch_to_preModEvent);
558  }
559 }
560 
562  auto const tNow = now();
563  auto const sid = stream_id(sc);
564  auto const mid = module_id(mcc);
565  auto t = duration_cast<duration_t>(tNow - beginTime_).count();
566  auto msg = assembleMessage<step::preModuleEvent>(sid, mid, toTransition(sc), t);
568 }
569 
571  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
572  auto msg = assembleMessage<step::postModuleEvent>(stream_id(sc), module_id(mcc), toTransition(sc), t);
574 }
575 
577  auto t = duration_cast<duration_t>(now() - beginTime_).count();
578  auto msg = assembleMessage<step::preModuleEvent>(numStreams_, module_id(mcc), toTransition(gc), t);
580 }
581 
583  auto const postModTime = duration_cast<duration_t>(now() - beginTime_).count();
584  auto msg = assembleMessage<step::postModuleEvent>(numStreams_, module_id(mcc), toTransition(gc), postModTime);
586 }
587 
589  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
590  auto msg = assembleMessage<step::preEventReadFromSource>(stream_id(sc), module_id(mcc), t);
592 }
593 
595  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
596  auto msg = assembleMessage<step::postEventReadFromSource>(stream_id(sc), module_id(mcc), t);
598 }
599 
601  auto const postModEvent = duration_cast<duration_t>(now() - beginTime_).count();
602  auto msg = assembleMessage<step::postModuleEvent>(
603  stream_id(sc), module_id(mcc), static_cast<std::underlying_type_t<Phase>>(Phase::Event), postModEvent);
605 }
606 
608  auto const t = duration_cast<duration_t>(now() - beginTime_).count();
609  auto const& eid = sc.eventID();
610  auto msg = assembleMessage<step::postEvent>(stream_id(sc), eid.run(), eid.luminosityBlock(), eid.event(), t);
612 }
613 
615  // Prepare summary
616  std::size_t width{};
617  edm::for_all(moduleStats_, [&width](auto const& stats) {
618  if (stats.numberOfStalls() == 0u)
619  return;
620  width = std::max(width, stats.label().size());
621  });
622 
623  OStreamColumn tag{"StallMonitor>"};
624  OStreamColumn col1{"Module label", width};
625  OStreamColumn col2{"# of stalls"};
626  OStreamColumn col3{"Total stalled time"};
627  OStreamColumn col4{"Max stalled time"};
628 
629  LogAbsolute out{"StallMonitor"};
630  out << '\n';
631  out << tag << space << col1 << space << col2 << space << col3 << space << col4 << '\n';
632 
633  out << tag << space << std::setfill('-') << col1(std::string{}) << space << col2(std::string{}) << space
634  << col3(std::string{}) << space << col4(std::string{}) << '\n';
635 
636  using seconds_d = duration<double>;
637 
638  auto to_seconds_str = [](auto const& duration) {
639  std::ostringstream oss;
640  auto const time = duration_cast<seconds_d>(duration).count();
641  oss << time << " s";
642  return oss.str();
643  };
644 
645  out << std::setfill(' ');
646  for (auto const& stats : moduleStats_) {
647  if (stats.label().empty() || // See comment in filling of moduleLabels_;
648  stats.numberOfStalls() == 0u)
649  continue;
650  out << std::left << tag << space << col1(stats.label()) << space << std::right << col2(stats.numberOfStalls())
651  << space << col3(to_seconds_str(stats.totalStalledTime())) << space
652  << col4(to_seconds_str(stats.maxStalledTime())) << '\n';
653  }
654 }
655 
size
Write out results.
Definition: start.py:1
ModuleDescription const * moduleDescription() const
void preModuleEvent(StreamContext const &, ModuleCallingContext const &)
void preSourceEvent(StreamID)
ThreadSafeOutputFileStream file_
void postEvent(StreamContext const &)
decltype(now()) beginTime_
std::vector< std::string > esModuleLabels_
std::string to_string(const V &value)
Definition: OMSAccess.h:71
Phase
std::ostream & operator<<(std::ostream &out, const ALILine &li)
Definition: ALILine.cc:167
assert(be >=bs)
void preModuleConstruction(edm::ModuleDescription const &)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:117
void preModuleStreamTransition(StreamContext const &, ModuleCallingContext const &)
void preModuleDestruction(edm::ModuleDescription const &)
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
Definition: Algorithms.h:14
T getUntrackedParameter(std::string const &, T const &) const
std::vector< std::string > moduleLabels_
char const * label
void postModuleEventPrefetching(StreamContext const &, ModuleCallingContext const &)
unsigned int id() const
void preEventReadFromSource(StreamContext const &, ModuleCallingContext const &)
duration_t const stallThreshold_
void preEvent(StreamContext const &)
Transition transition() const
Definition: StreamContext.h:56
rep
Definition: cuy.py:1189
void preModuleEventAcquire(StreamContext const &, ModuleCallingContext const &)
#define DEFINE_FWK_SERVICE(type)
Definition: ServiceMaker.h:97
void setComment(std::string const &value)
void postModuleEventAcquire(StreamContext const &, ModuleCallingContext const &)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void postEventReadFromSource(StreamContext const &, ModuleCallingContext const &)
void postModuleGlobalTransition(GlobalContext const &, ModuleCallingContext const &)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
tuple msg
Definition: mps_check.py:286
oneapi::tbb::concurrent_unordered_map< std::pair< StreamID_value, ModuleID >, std::pair< decltype(beginTime_), bool >, edm::StdPairHasher > stallStart_
Transition transition() const
Definition: GlobalContext.h:55
void postModuleStreamTransition(StreamContext const &, ModuleCallingContext const &)
void postSourceEvent(StreamID)
void postModuleEvent(StreamContext const &, ModuleCallingContext const &)
decltype(std::declval< StreamID >().value()) StreamID_value
HLT enums.
#define update(a, b)
EventID const & eventID() const
Definition: StreamContext.h:60
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< StallStatistics > moduleStats_
step
Definition: StallMonitor.cc:98
unsigned int value() const
Definition: StreamID.h:43
decltype(std::declval< ModuleDescription >().id()) ModuleID
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
long double T
std::string const & moduleLabel() const
def move(src, dest)
Definition: eostools.py:511
edm::eventsetup::ComponentDescription const * componentDescription() const
void preModuleGlobalTransition(GlobalContext const &, ModuleCallingContext const &)