The Gaudi Framework  master (37c0b60a)
AlgTimingAuditor.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 2023 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #include <GaudiKernel/Auditor.h>
14 #include <GaudiKernel/SmartIF.h>
15 #include <chrono>
16 #include <fmt/format.h>
17 #include <string>
18 #include <type_traits>
19 #include <unordered_map>
20 #include <vector>
21 
22 struct AlgTimingAuditor final : extends<Auditor, IIncidentListener> {
24 
25  using Auditor::after;
26  using Auditor::before;
27 
28  StatusCode initialize() override {
29  return base_class::initialize().andThen( [&]() {
30  m_incSvc = service( "IncidentSvc" );
31  if ( m_incSvc ) {
32  m_incSvc->addListener( this, IncidentType::BeginEvent );
33  m_incSvc->addListener( this, IncidentType::EndEvent );
35  } else {
36  debug() << "no IncidentSvc, I cannot measure overall event processing time" << endmsg;
37  }
38  } );
39  }
40 
41  void before( StandardEventType evt, INamedInterface* alg ) override {
42  if ( !alg ) return;
43  switch ( evt ) {
44  case Initialize:
45  stats( alg ); // this implicitly adds the algorithm to the list of known ones
47  break;
48 
49  case Execute:
50  stats( alg ).start();
51  break;
52 
53  default:
54  break;
55  }
56  }
57 
58  void after( StandardEventType evt, INamedInterface* alg, const StatusCode& ) override {
59  if ( !alg ) return;
60  switch ( evt ) {
61  case Initialize:
63  break;
64 
65  case Execute:
66  stats( alg ).stop();
67  break;
68 
69  default:
70  break;
71  }
72  }
73 
74  void handle( const Incident& i ) override {
75  if ( IncidentType::BeginEvent == i.type() ) {
77  } else if ( IncidentType::EndEvent == i.type() ) {
79  }
80  }
81 
82  StatusCode finalize() override {
85  info() << "-------------------------------------------------------------------" << endmsg;
86  info() << "Algorithm | exec (ms) | count | total (s)" << endmsg;
87  info() << "-------------------------------------------------------------------" << endmsg;
88  if ( m_incSvc ) {
89  const auto count = m_eventLoopStats.count;
90  const auto total_time = m_eventLoopStats.total_time;
91  info() << fmt::format( "{:<30.30} | {:9.4} | {:9} | {:9.4}", "EVENT LOOP",
92  count ? ms( total_time ).count() / count : 0.f, count, s( total_time ).count() )
93  << endmsg;
94  }
96  std::sort( begin( offsets ), end( offsets ), []( auto& a, auto& b ) { return a.second < b.second; } );
97  for ( const auto& [name, offset] : offsets ) {
98  std::string indented_name = std::string( m_depths[offset], ' ' ) + name;
99  const auto count = m_stats[offset].count;
100  const auto total_time = m_stats[offset].total_time;
101  info() << fmt::format( "{:<30.30} | {:9.4} | {:9} | {:9.4}", indented_name,
102  count ? ms( total_time ).count() / count : 0.f, count, s( total_time ).count() )
103  << endmsg;
104  }
105  info() << "-------------------------------------------------------------------" << endmsg;
106 
107  if ( m_incSvc ) {
108  m_incSvc->removeListener( this, IncidentType::BeginEvent );
109  m_incSvc->removeListener( this, IncidentType::EndEvent );
110  m_incSvc.reset();
111  }
112  return base_class::finalize();
113  }
114 
115  using clock_t = std::conditional_t<std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock,
117 
118  struct stats_t {
119  clock_t::duration total_time{};
121  clock_t::time_point started{};
122 
123  void start() { started = clock_t::now(); }
124  void stop() {
125  total_time += clock_t::now() - started;
126  ++count;
127  }
128  };
129 
131  if ( auto it = m_offsets.find( alg->name() ); it != end( m_offsets ) ) {
132  return m_stats[it->second];
133  } else {
135  m_stats.emplace_back();
136  m_offsets[alg->name()] = m_stats.size() - 1;
137  return m_stats.back();
138  }
139  }
140 
142 
148 };
149 
IOTest.evt
evt
Definition: IOTest.py:107
AlgTimingAuditor::stats_t::start
void start()
Definition: AlgTimingAuditor.cpp:123
std::chrono::steady_clock
AlgTimingAuditor::finalize
StatusCode finalize() override
Definition: AlgTimingAuditor.cpp:82
std::string
STL class.
StatusCode::andThen
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
Definition: StatusCode.h:163
AlgTimingAuditor::m_offsets
std::unordered_map< std::string, std::size_t > m_offsets
Definition: AlgTimingAuditor.cpp:143
AlgTimingAuditor::before
void before(StandardEventType evt, INamedInterface *alg) override
Definition: AlgTimingAuditor.cpp:41
gaudirun.s
string s
Definition: gaudirun.py:346
std::vector
STL class.
SmartIF::reset
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:96
std::unordered_map::find
T find(T... args)
std::chrono::duration
Auditor::before
void before(StandardEventType, INamedInterface *) override
The following methods are meant to be implemented by the child class...
Definition: Auditor.cpp:82
AlgTimingAuditor::m_stats
std::vector< stats_t > m_stats
Definition: AlgTimingAuditor.cpp:145
AlgTimingAuditor::stats_t::count
std::size_t count
Definition: AlgTimingAuditor.cpp:120
AlgTimingAuditor::m_currentDepth
std::uint16_t m_currentDepth
Definition: AlgTimingAuditor.cpp:147
AlgTimingAuditor::stats_t::started
clock_t::time_point started
Definition: AlgTimingAuditor.cpp:121
std::sort
T sort(T... args)
AlgTimingAuditor::stats
stats_t & stats(INamedInterface *alg)
Definition: AlgTimingAuditor.cpp:130
AlgTimingAuditor::after
void after(StandardEventType evt, INamedInterface *alg, const StatusCode &) override
Definition: AlgTimingAuditor.cpp:58
std::chrono::high_resolution_clock
Gaudi::Units::ms
constexpr double ms
Definition: SystemOfUnits.h:154
IIncidentSvc.h
std::vector::push_back
T push_back(T... args)
ManySmallAlgs.alg
alg
Definition: ManySmallAlgs.py:81
Auditor::name
const std::string & name() const override
Definition: Auditor.cpp:192
SmartIF.h
Auditor::after
void after(StandardEventType, INamedInterface *, const StatusCode &) override
Definition: Auditor.cpp:112
Gaudi::Utils::begin
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Definition: AttribStringParser.h:136
AlgTimingAuditor::stats_t::stop
void stop()
Definition: AlgTimingAuditor.cpp:124
StatusCode
Definition: StatusCode.h:65
AlgTimingAuditor::handle
void handle(const Incident &i) override
Definition: AlgTimingAuditor.cpp:74
AlgTimingAuditor::m_incSvc
SmartIF< IIncidentSvc > m_incSvc
Definition: AlgTimingAuditor.cpp:141
AlgTimingAuditor::stats_t::total_time
clock_t::duration total_time
Definition: AlgTimingAuditor.cpp:119
AlgTimingAuditor::stats_t
Definition: AlgTimingAuditor.cpp:118
SmartIF< IIncidentSvc >
std::uint16_t
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:20
INamedInterface
Definition: INamedInterface.h:25
IIncidentListener.h
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
AlgTimingAuditor
Definition: AlgTimingAuditor.cpp:22
AlgTimingAuditor::m_depths
std::vector< std::uint16_t > m_depths
Definition: AlgTimingAuditor.cpp:144
std::size_t
Incident::type
const std::string & type() const
Access to the incident type.
Definition: Incident.h:48
IOTest.end
end
Definition: IOTest.py:125
AlgTimingAuditor::clock_t
std::conditional_t< std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock > clock_t
Definition: AlgTimingAuditor.cpp:116
CommonMessaging::base_class
CommonMessaging base_class
Definition: CommonMessaging.h:142
Incident
Definition: Incident.h:27
AlgTimingAuditor::m_eventLoopStats
stats_t m_eventLoopStats
Definition: AlgTimingAuditor.cpp:146
AlgTimingAuditor::initialize
StatusCode initialize() override
Definition: AlgTimingAuditor.cpp:28
Auditor::service
StatusCode service(std::string_view name, T *&svc, bool createIf=false) const
Access a service by name, creating it if it doesn't already exist.
Definition: Auditor.h:108
std::unordered_map< std::string, std::size_t >
Auditor.h