The Gaudi Framework  master (d98a2936)
AlgTimingAuditor.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 2023-2025 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 <Gaudi/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<Gaudi::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( std::string const& evt, std::string const& alg, EventContext const& ) override {
43  stats( alg ); // this implicitly adds the algorithm to the list of known ones
45  } else if ( evt == Gaudi::IAuditor::Execute ) {
46  stats( alg ).start();
47  }
48  }
49 
50  void after( std::string const& evt, std::string const& alg, EventContext const&, const StatusCode& ) override {
53  } else if ( evt == Gaudi::IAuditor::Execute ) {
54  stats( alg ).stop();
55  }
56  }
57 
58  void handle( const Incident& i ) override {
59  if ( IncidentType::BeginEvent == i.type() ) {
61  } else if ( IncidentType::EndEvent == i.type() ) {
63  }
64  }
65 
66  StatusCode finalize() override {
67  using ms = std::chrono::duration<float, std::milli>;
68  using s = std::chrono::duration<float>;
69  info() << "-------------------------------------------------------------------" << endmsg;
70  info() << "Algorithm | exec (ms) | count | total (s)" << endmsg;
71  info() << "-------------------------------------------------------------------" << endmsg;
72  if ( m_incSvc ) {
73  const auto count = m_eventLoopStats.count;
74  const auto total_time = m_eventLoopStats.total_time;
75  info() << fmt::format( "{:<30.30} | {:9.4} | {:9} | {:9.4}", "EVENT LOOP",
76  count ? ms( total_time ).count() / count : 0.f, count, s( total_time ).count() )
77  << endmsg;
78  }
79  std::vector<std::pair<std::string, std::size_t>> offsets{ begin( m_offsets ), end( m_offsets ) };
80  std::sort( begin( offsets ), end( offsets ), []( auto& a, auto& b ) { return a.second < b.second; } );
81  for ( const auto& [name, offset] : offsets ) {
82  std::string indented_name = std::string( m_depths[offset], ' ' ) + name;
83  const auto count = m_stats[offset].count;
84  const auto total_time = m_stats[offset].total_time;
85  info() << fmt::format( "{:<30.30} | {:9.4} | {:9} | {:9.4}", indented_name,
86  count ? ms( total_time ).count() / count : 0.f, count, s( total_time ).count() )
87  << endmsg;
88  }
89  info() << "-------------------------------------------------------------------" << endmsg;
90 
91  if ( m_incSvc ) {
92  m_incSvc->removeListener( this, IncidentType::BeginEvent );
93  m_incSvc->removeListener( this, IncidentType::EndEvent );
94  m_incSvc.reset();
95  }
96  return base_class::finalize();
97  }
98 
99  using clock_t = std::conditional_t<std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock,
100  std::chrono::steady_clock>;
101 
102  struct stats_t {
103  clock_t::duration total_time{};
104  std::size_t count{};
105  clock_t::time_point started{};
106 
107  void start() { started = clock_t::now(); }
108  void stop() {
109  total_time += clock_t::now() - started;
110  ++count;
111  }
112  };
113 
114  stats_t& stats( std::string const& alg ) {
115  if ( auto it = m_offsets.find( alg ); it != end( m_offsets ) ) {
116  return m_stats[it->second];
117  } else {
118  m_depths.push_back( m_currentDepth );
119  m_stats.emplace_back();
120  m_offsets[alg] = m_stats.size() - 1;
121  return m_stats.back();
122  }
123  }
124 
126 
127  std::unordered_map<std::string, std::size_t> m_offsets;
128  std::vector<std::uint16_t> m_depths;
129  std::vector<stats_t> m_stats;
131  std::uint16_t m_currentDepth{ 0 };
132 };
133 
IOTest.evt
evt
Definition: IOTest.py:107
AlgTimingAuditor::stats_t::start
void start()
Definition: AlgTimingAuditor.cpp:107
Gaudi::IAuditor::Execute
static const std::string Execute
Definition: IAuditor.h:51
AlgTimingAuditor::finalize
StatusCode finalize() override
Definition: AlgTimingAuditor.cpp:66
Gaudi::IAuditor::Initialize
static const std::string Initialize
Definition: IAuditor.h:47
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:127
gaudirun.s
string s
Definition: gaudirun.py:346
SmartIF::reset
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:88
AlgTimingAuditor::after
void after(std::string const &evt, std::string const &alg, EventContext const &, const StatusCode &) override
Definition: AlgTimingAuditor.cpp:50
AlgTimingAuditor::m_stats
std::vector< stats_t > m_stats
Definition: AlgTimingAuditor.cpp:129
AlgTimingAuditor::stats_t::count
std::size_t count
Definition: AlgTimingAuditor.cpp:104
AlgTimingAuditor::m_currentDepth
std::uint16_t m_currentDepth
Definition: AlgTimingAuditor.cpp:131
AlgTimingAuditor::stats_t::started
clock_t::time_point started
Definition: AlgTimingAuditor.cpp:105
Gaudi::Units::ms
constexpr double ms
Definition: SystemOfUnits.h:153
IIncidentSvc.h
ManySmallAlgs.alg
alg
Definition: ManySmallAlgs.py:81
SmartIF.h
Gaudi::Utils::begin
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Definition: AttribStringParser.h:135
AlgTimingAuditor::stats
stats_t & stats(std::string const &alg)
Definition: AlgTimingAuditor.cpp:114
AlgTimingAuditor::stats_t::stop
void stop()
Definition: AlgTimingAuditor.cpp:108
StatusCode
Definition: StatusCode.h:64
AlgTimingAuditor::handle
void handle(const Incident &i) override
Definition: AlgTimingAuditor.cpp:58
AlgTimingAuditor::m_incSvc
SmartIF< IIncidentSvc > m_incSvc
Definition: AlgTimingAuditor.cpp:125
Gaudi::Auditor::name
const std::string & name() const override
Definition: Auditor.h:51
AlgTimingAuditor::stats_t::total_time
clock_t::duration total_time
Definition: AlgTimingAuditor.cpp:103
AlgTimingAuditor::stats_t
Definition: AlgTimingAuditor.cpp:102
SmartIF< IIncidentSvc >
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:93
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:198
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:19
AlgTimingAuditor::before
void before(std::string const &evt, std::string const &alg, EventContext const &) override
Definition: AlgTimingAuditor.cpp:41
IIncidentListener.h
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:45
EventContext
Definition: EventContext.h:34
AlgTimingAuditor
Definition: AlgTimingAuditor.cpp:22
AlgTimingAuditor::m_depths
std::vector< std::uint16_t > m_depths
Definition: AlgTimingAuditor.cpp:128
Incident::type
const std::string & type() const
Access to the incident type.
Definition: Incident.h:43
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:100
CommonMessaging::base_class
CommonMessaging base_class
Definition: CommonMessaging.h:141
Incident
Definition: Incident.h:24
AlgTimingAuditor::m_eventLoopStats
stats_t m_eventLoopStats
Definition: AlgTimingAuditor.cpp:130
Gaudi::Auditor::service
SmartIF< T > service(std::string_view name, bool createIf=false) const
Access a service by name, creating it if it doesn't already exist.
Definition: Auditor.h:63
AlgTimingAuditor::initialize
StatusCode initialize() override
Definition: AlgTimingAuditor.cpp:28
Auditor.h