28 #include "tbb/concurrent_unordered_map.h"
38 using duration_t = std::chrono::microseconds;
39 using clock_t = std::chrono::steady_clock;
47 class StallStatistics {
52 StallStatistics() =
default;
55 unsigned numberOfStalls()
const {
return stallCounter_; }
59 duration_t totalStalledTime()
const {
return duration_t{totalTime_.load()}; }
60 duration_t maxStalledTime()
const {
return duration_t{maxTime_.load()}; }
65 void update(duration_t
const ms) {
67 auto const thisTime = ms.count();
68 totalTime_ += thisTime;
70 while (thisTime >
max && !maxTime_.compare_exchange_strong(
max, thisTime))
76 std::atomic<unsigned> stallCounter_{};
77 std::atomic<rep_t> totalTime_{};
78 std::atomic<rep_t> maxTime_{};
88 template <
typename H,
typename...
T>
91 concatenate(os, t...);
96 postSourceEvent =
's',
98 postModuleEventPrefetching =
'p',
99 preModuleEventAcquire =
'A',
100 postModuleEventAcquire =
'a',
101 preModuleEvent =
'M',
102 preEventReadFromSource =
'R',
103 postEventReadFromSource =
'r',
104 postModuleEvent =
'm',
121 os << static_cast<std::underlying_type_t<step>>(
s);
126 os << static_cast<std::underlying_type_t<Phase>>(
s);
130 template <
step S,
typename... ARGS>
132 std::ostringstream oss;
134 concatenate(oss, args...);
142 case StreamContext::Transition::kBeginRun:
143 return Phase::streamBeginRun;
144 case StreamContext::Transition::kBeginLuminosityBlock:
145 return Phase::streamBeginLumi;
146 case StreamContext::Transition::kEvent:
148 case StreamContext::Transition::kEndLuminosityBlock:
149 return Phase::streamEndLumi;
150 case StreamContext::Transition::kEndRun:
151 return Phase::streamEndRun;
159 auto toTransition(
edm::StreamContext const& iContext) -> std::underlying_type_t<Phase> {
160 return static_cast<std::underlying_type_t<Phase>
>(toTransitionImpl(iContext));
166 case GlobalContext::Transition::kBeginRun:
167 return Phase::globalBeginRun;
168 case GlobalContext::Transition::kBeginLuminosityBlock:
169 return Phase::globalBeginLumi;
170 case GlobalContext::Transition::kEndLuminosityBlock:
171 return Phase::globalEndLumi;
172 case GlobalContext::Transition::kWriteLuminosityBlock:
173 return Phase::globalEndLumi;
174 case GlobalContext::Transition::kEndRun:
175 return Phase::globalEndRun;
176 case GlobalContext::Transition::kWriteRun:
177 return Phase::globalEndRun;
184 auto toTransition(
edm::GlobalContext const& iContext) -> std::underlying_type_t<Phase> {
185 return static_cast<std::underlying_type_t<Phase>
>(toTransitionImpl(iContext));
222 decltype(
now()) beginTime_{};
229 using ModuleID = decltype(std::declval<ModuleDescription>().
id());
230 tbb::concurrent_unordered_map<std::pair<StreamID_value, ModuleID>,
231 std::pair<decltype(beginTime_), bool>,
235 std::vector<std::string> moduleLabels_{};
236 std::vector<StallStatistics> moduleStats_{};
245 constexpr
char const*
const filename_default{
""};
246 constexpr
double threshold_default{0.1};
251 using namespace std::chrono;
257 std::chrono::round<duration_t>(duration<double>(iPS.
getUntrackedParameter<
double>(
"stallThreshold")))} {
304 std::ostringstream oss;
305 oss <<
"# Transition Symbol\n";
306 oss <<
"#----------------- ------\n";
307 oss <<
"# globalBeginRun " << Phase::globalBeginRun <<
"\n"
308 <<
"# streamBeginRun " << Phase::streamBeginRun <<
"\n"
309 <<
"# globalBeginLumi " << Phase::globalBeginLumi <<
"\n"
310 <<
"# streamBeginLumi " << Phase::streamBeginLumi <<
"\n"
312 <<
"# streamEndLumi " << Phase::streamEndLumi <<
"\n"
313 <<
"# globalEndLumi " << Phase::globalEndLumi <<
"\n"
314 <<
"# streamEndRun " << Phase::streamEndRun <<
"\n"
315 <<
"# globalEndRun " << Phase::globalEndRun <<
"\n";
316 oss <<
"# Step Symbol Entries\n"
317 <<
"# -------------------------- ------ ------------------------------------------\n"
318 <<
"# preSourceEvent " << step::preSourceEvent <<
" <Stream ID> <Time since beginJob (ms)>\n"
319 <<
"# postSourceEvent " << step::postSourceEvent <<
" <Stream ID> <Time since beginJob (ms)>\n"
320 <<
"# preEvent " << step::preEvent
321 <<
" <Stream ID> <Run#> <LumiBlock#> <Event#> <Time since beginJob (ms)>\n"
322 <<
"# postModuleEventPrefetching " << step::postModuleEventPrefetching
323 <<
" <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
324 <<
"# preModuleEventAcquire " << step::preModuleEventAcquire
325 <<
" <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
326 <<
"# postModuleEventAcquire " << step::postModuleEventAcquire
327 <<
" <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
328 <<
"# preModuleTransition " << step::preModuleEvent
329 <<
" <Stream ID> <Module ID> <Transition type> <Time since beginJob (ms)>\n"
330 <<
"# preEventReadFromSource " << step::preEventReadFromSource
331 <<
" <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
332 <<
"# postEventReadFromSource " << step::postEventReadFromSource
333 <<
" <Stream ID> <Module ID> <Time since beginJob (ms)>\n"
334 <<
"# postModuleTransition " << step::postModuleEvent
335 <<
" <Stream ID> <Module ID> <Transition type> <Time since beginJob (ms)>\n"
336 <<
"# postEvent " << step::postEvent
337 <<
" <Stream ID> <Run#> <LumiBlock#> <Event#> <Time since beginJob (ms)>\n";
346 "Name of file to which detailed timing information should be written.\n"
347 "An empty filename argument (the default) indicates that no extra\n"
348 "information will be written to a dedicated file, but only the summary\n"
349 "including stalling-modules information will be logged.");
350 desc.
addUntracked<
double>(
"stallThreshold", threshold_default)
352 "Threshold (in seconds) used to classify modules as stalled.\n"
353 "Microsecond granularity allowed.");
354 descriptions.
add(
"StallMonitor", desc);
356 "This service keeps track of various times in event-processing to determine which modules are stalling.");
371 auto const mid = md.
id();
402 std::ostringstream oss;
403 oss <<
"\n# " << col0 << space << lastCol <<
'\n';
404 oss <<
"# " <<
std::string(col0.width() + space.size() + lastCol.size(),
'-') <<
'\n';
410 oss <<
"#M " << std::setw(width) << std::left << col0(
i) << space << std::left <<
moduleLabels_[
i] <<
'\n';
424 auto msg = assembleMessage<step::preSourceEvent>(sid.
value(),
t);
430 auto msg = assembleMessage<step::postSourceEvent>(sid.
value(),
t);
437 auto msg = assembleMessage<step::preEvent>(stream_id(sc),
eid.run(),
eid.luminosityBlock(),
eid.event(),
t);
442 auto const sid = stream_id(sc);
443 auto const mid = module_id(mcc);
448 auto msg = assembleMessage<step::postModuleEventPrefetching>(sid, mid,
t);
454 auto const preModEventAcquire =
now();
455 auto const sid = stream_id(sc);
456 auto const mid = module_id(mcc);
458 auto startT =
start.first.time_since_epoch();
461 auto t = duration_cast<duration_t>(preModEventAcquire -
beginTime_).
count();
462 auto msg = assembleMessage<step::preModuleEventAcquire>(sid, mid,
t);
467 auto const preFetch_to_preModEventAcquire = duration_cast<duration_t>(preModEventAcquire -
start.first);
470 moduleStats_[mid].update(preFetch_to_preModEventAcquire);
475 auto const postModEventAcquire = duration_cast<duration_t>(
now() -
beginTime_).
count();
476 auto msg = assembleMessage<step::postModuleEventAcquire>(stream_id(sc), module_id(mcc), postModEventAcquire);
481 auto const preModEvent =
now();
482 auto const sid = stream_id(sc);
483 auto const mid = module_id(mcc);
485 auto startT =
start.first.time_since_epoch();
489 assembleMessage<step::preModuleEvent>(sid, mid,
static_cast<std::underlying_type_t<Phase>
>(
Phase::Event),
t);
494 auto const preFetch_to_preModEvent = duration_cast<duration_t>(preModEvent -
start.first);
502 auto const tNow =
now();
503 auto const sid = stream_id(sc);
504 auto const mid = module_id(mcc);
506 auto msg = assembleMessage<step::preModuleEvent>(sid, mid, toTransition(sc),
t);
512 auto msg = assembleMessage<step::postModuleEvent>(stream_id(sc), module_id(mcc), toTransition(sc),
t);
518 auto msg = assembleMessage<step::preModuleEvent>(
numStreams_, module_id(mcc), toTransition(gc),
t);
524 auto msg = assembleMessage<step::postModuleEvent>(
numStreams_, module_id(mcc), toTransition(gc), postModTime);
530 auto msg = assembleMessage<step::preEventReadFromSource>(stream_id(sc), module_id(mcc),
t);
536 auto msg = assembleMessage<step::postEventReadFromSource>(stream_id(sc), module_id(mcc),
t);
542 auto msg = assembleMessage<step::postModuleEvent>(
543 stream_id(sc), module_id(mcc),
static_cast<std::underlying_type_t<Phase>
>(
Phase::Event), postModEvent);
550 auto msg = assembleMessage<step::postEvent>(stream_id(sc),
eid.run(),
eid.luminosityBlock(),
eid.event(),
t);
558 if (
stats.numberOfStalls() == 0u)
571 out <<
tag << space << col1 << space << col2 << space << col3 << space << col4 <<
'\n';
576 using seconds_d = duration<double>;
578 auto to_seconds_str = [](
auto const& duration) {
579 std::ostringstream oss;
580 auto const time = duration_cast<seconds_d>(duration).
count();
585 out << std::setfill(
' ');
587 if (
stats.label().empty() ||
588 stats.numberOfStalls() == 0u)
590 out << std::left <<
tag << space << col1(
stats.label()) << space << std::right << col2(
stats.numberOfStalls())
591 << space << col3(to_seconds_str(
stats.totalStalledTime())) << space
592 << col4(to_seconds_str(
stats.maxStalledTime())) <<
'\n';
void watchPostModuleGlobalEndLumi(PostModuleGlobalEndLumi::slot_type const &iSlot)
void watchPreModuleGlobalBeginRun(PreModuleGlobalBeginRun::slot_type const &iSlot)
T getUntrackedParameter(std::string const &, T const &) const
void watchPreEvent(PreEvent::slot_type const &iSlot)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void preModuleEvent(StreamContext const &, ModuleCallingContext const &)
void watchPreModuleEventAcquire(PreModuleEventAcquire::slot_type const &iSlot)
void watchPostEndJob(PostEndJob::slot_type const &iSlot)
void watchPreModuleEvent(PreModuleEvent::slot_type const &iSlot)
void watchPreModuleConstruction(PreModuleConstruction::slot_type const &iSlot)
void preSourceEvent(StreamID)
unique_ptr< ClusterSequence > cs
ThreadSafeOutputFileStream file_
void watchPostEvent(PostEvent::slot_type const &iSlot)
void postEvent(StreamContext const &)
decltype(now()) beginTime_
void watchPreEventReadFromSource(PreEventReadFromSource::slot_type const &iSlot)
void watchPreModuleDestruction(PreModuleDestruction::slot_type const &iSlot)
void watchPostModuleEvent(PostModuleEvent::slot_type const &iSlot)
void watchPostModuleGlobalBeginLumi(PostModuleGlobalBeginLumi::slot_type const &iSlot)
void watchPostModuleStreamEndLumi(PostModuleStreamEndLumi::slot_type const &iSlot)
void watchPostModuleStreamBeginRun(PostModuleStreamBeginRun::slot_type const &iSlot)
void watchPostSourceEvent(PostSourceEvent::slot_type const &iSlot)
std::ostream & operator<<(std::ostream &out, const ALILine &li)
std::string const & moduleLabel() const
void watchPreModuleGlobalEndRun(PreModuleGlobalEndRun::slot_type const &iSlot)
void preModuleConstruction(edm::ModuleDescription const &)
void watchPostModuleWriteRun(PostModuleWriteRun::slot_type const &iSlot)
void preModuleStreamTransition(StreamContext const &, ModuleCallingContext const &)
void preModuleDestruction(edm::ModuleDescription const &)
void watchPostModuleWriteLumi(PostModuleWriteLumi::slot_type const &iSlot)
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
Preallocate preallocateSignal_
signal is emitted before beginJob
void watchPostModuleEventPrefetching(PostModuleEventPrefetching::slot_type const &iSlot)
unsigned int maxNumberOfStreams() const
std::vector< std::string > moduleLabels_
Transition transition() const
void postModuleEventPrefetching(StreamContext const &, ModuleCallingContext const &)
void preEventReadFromSource(StreamContext const &, ModuleCallingContext const &)
ModuleDescription const * moduleDescription() const
void watchPostModuleEventAcquire(PostModuleEventAcquire::slot_type const &iSlot)
duration_t const stallThreshold_
void preEvent(StreamContext const &)
void watchPreModuleGlobalBeginLumi(PreModuleGlobalBeginLumi::slot_type const &iSlot)
void watchPostModuleStreamEndRun(PostModuleStreamEndRun::slot_type const &iSlot)
StreamID const & streamID() const
void watchPreModuleStreamBeginLumi(PreModuleStreamBeginLumi::slot_type const &iSlot)
void preModuleEventAcquire(StreamContext const &, ModuleCallingContext const &)
#define DEFINE_FWK_SERVICE(type)
void setComment(std::string const &value)
void postModuleEventAcquire(StreamContext const &, ModuleCallingContext const &)
unsigned int value() const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void postEventReadFromSource(StreamContext const &, ModuleCallingContext const &)
void watchPostModuleGlobalEndRun(PostModuleGlobalEndRun::slot_type const &iSlot)
void postModuleGlobalTransition(GlobalContext const &, ModuleCallingContext const &)
void watchPostModuleStreamBeginLumi(PostModuleStreamBeginLumi::slot_type const &iSlot)
void watchPreModuleStreamEndLumi(PreModuleStreamEndLumi::slot_type const &iSlot)
void watchPreModuleStreamBeginRun(PreModuleStreamBeginRun::slot_type const &iSlot)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
double S(const TLorentzVector &, const TLorentzVector &)
void watchPreModuleWriteRun(PreModuleWriteRun::slot_type const &iSlot)
tbb::concurrent_unordered_map< std::pair< StreamID_value, ModuleID >, std::pair< decltype(beginTime_), bool >, edm::StdPairHasher > stallStart_
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
void watchPreModuleStreamEndRun(PreModuleStreamEndRun::slot_type const &iSlot)
void watchPostEventReadFromSource(PostEventReadFromSource::slot_type const &iSlot)
void watchPostModuleGlobalBeginRun(PostModuleGlobalBeginRun::slot_type const &iSlot)
void watchPreModuleWriteLumi(PreModuleWriteLumi::slot_type const &iSlot)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< StallStatistics > moduleStats_
EventID const & eventID() const
void watchPreSourceEvent(PreSourceEvent::slot_type const &iSlot)
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.
void write(std::string &&msg)
tuple size
Write out results.
void watchPreModuleGlobalEndLumi(PreModuleGlobalEndLumi::slot_type const &iSlot)
void preModuleGlobalTransition(GlobalContext const &, ModuleCallingContext const &)
void watchPostBeginJob(PostBeginJob::slot_type const &iSlot)
convenience function for attaching to signal