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