9#include "GaudiKernel/IIncidentSvc.h"
19#include <boost/algorithm/string.hpp>
25 ISvcLocator* pSvcLocator)
26 : Auditor(name, pSvcLocator),
27 m_valSvc(
"ValgrindSvc", this->name()),
30 declareProperty(
"ProfiledAlgs",
m_algs,
31 "List of algorithms to run in valgrind");
34 "Intervals to profile (e.g. 'MyAlg.initialize:MyAlg.finalize'" );
37 "Do not profile the first N events");
40 "Dump separate profile after each interval in ProfiledIntervals" );
51 if ( !
m_valSvc.retrieve().isSuccess()) {
52 msgStream() << MSG::ERROR <<
"Could not retrieve the ValgrindSvc" <<
endmsg;
53 return StatusCode::FAILURE;
56 const IProperty* valSvcProp =
dynamic_cast<const IProperty*
>(&(*m_valSvc));
58 msgStream() << MSG::ERROR
59 <<
"Could not retrieve IProperty interface to ValgrindSvc."
61 return StatusCode::FAILURE;
67 msgStream() << MSG::VERBOSE
68 <<
"Initializing " << name() <<
"..."
72 std::string properties[] = {
"ProfiledAlgs",
75 "DumpAfterEachInterval"};
77 for( std::string prop : properties ) {
78 if ( !
setProperty(valSvcProp->getProperty(prop)) ) {
79 msgStream() << MSG::ERROR <<
"Cannot set " << prop <<
" property." <<
endmsg;
80 return StatusCode::FAILURE;
88 for(
const std::string&
re :
m_algs ) {
92 catch (
const boost::regex_error& ) {
93 msgStream() << MSG::ERROR <<
"Ignoring invalid regular expression: " <<
re <<
endmsg;
97 if ( msgLevel() <= MSG::INFO ) {
98 std::ostringstream out;
101 std::ostream_iterator<std::string>( out,
" " ) );
103 msgStream() << MSG::INFO <<
"Profiled algorithms: " << out.str() <<
endmsg;
108 std::ostream_iterator<std::string>( out,
" " ) );
110 msgStream() << MSG::INFO <<
"Profiled intervals: " << out.str() <<
endmsg;
115 msgStream() << MSG::ERROR <<
"Syntax error in ProfiledIntervals" <<
endmsg;
116 return StatusCode::FAILURE;
122 if ( !incSvc.retrieve().isSuccess() ) {
123 msgStream() << MSG::ERROR <<
"Unable to get the IncidentSvc" <<
endmsg;
124 return StatusCode::FAILURE;
127 const long prio = std::numeric_limits<long>::max();
129 incSvc->addListener(
this, IncidentType::BeginEvent, prio );
131 for(
const std::pair<NameEvt,NameEvt>&
h :
m_hooks ) {
133 if (
h.first.second==
"incident" ) incSvc->addListener(
this,
h.first.first.str(), prio );
134 if (
h.second.second==
"incident" ) incSvc->addListener(
this,
h.second.first.str(), prio );
137 return StatusCode::SUCCESS;
147 if ( inc.type() == IncidentType::BeginEvent ) {
154 if (
h->first.second==
"incident" )
do_before(inc.type(),
"incident");
155 if (
h->second.second==
"incident" )
do_after(inc.type(),
"incident");
167 else do_before(name, boost::to_lower_copy(event));
171 const EventContext&,
const StatusCode&)
174 else do_after(name, boost::to_lower_copy(event));
185 if ( msgLevel() <= MSG::DEBUG )
186 msgStream() << MSG::DEBUG <<
"Starting callgrind before execute of " << name
189 m_valSvc->callgrindStartInstrumentation();
202 m_valSvc->callgrindStopInstrumentation();
203 if ( msgLevel() <= MSG::DEBUG )
204 msgStream() << MSG::DEBUG <<
"Stopping callgrind after execute of " << name
219 if ( boost::regex_match(name, iter->first.first) &&
220 iter->first.second == hook ) {
221 m_valSvc->callgrindStartInstrumentation();
222 if ( msgLevel() <= MSG::DEBUG )
223 msgStream() << MSG::DEBUG <<
"Starting callgrind before " << hook
224 <<
" of " << name <<
endmsg;
237 if ( boost::regex_match(name, iter->second.first) &&
238 iter->second.second == hook ) {
239 m_valSvc->callgrindStopInstrumentation();
240 if ( msgLevel() <= MSG::DEBUG )
241 msgStream() << MSG::DEBUG <<
"Stopping callgrind after " << hook
242 <<
" of " << name <<
endmsg;
245 m_valSvc->callgrindDumpStats(msgStream().stream());
246 msgStream() << MSG::INFO <<
"Creating callgrind profile #" <<
m_valSvc->profileCount()
247 <<
" after " << hook <<
" of " << name <<
endmsg;
263 string::size_type loc = s.rfind(
'.');
264 if ( loc==string::npos )
return StatusCode::FAILURE;
267 nameEvt.first = boost::regex(s.substr(0,loc));
269 catch (
const boost::regex_error& ) {
270 return StatusCode::FAILURE;
273 nameEvt.second =
s.substr(loc+1);
275 return StatusCode::SUCCESS;
284 std::vector<string>::const_iterator iter =
m_intervals.begin();
286 const string& spec = *iter;
287 string::size_type loc = spec.find(
':');
291 if (loc==string::npos) s1 = s2 = spec;
293 s1 = spec.substr(0,loc);
294 s2 = spec.substr(loc+1);
298 if ( s1==
"" || s2==
"" ||
299 decodeNameEvt(s1,ne1).isFailure() || decodeNameEvt(s2,ne2).isFailure() ) {
300 msgStream() << MSG::ERROR <<
"Invalid profiling interval [" << spec <<
"]" <<
endmsg;
301 return StatusCode::FAILURE;
304 std::pair<NameEvt,NameEvt> p(ne1,ne2);
305 m_hooks.emplace_back(std::move(p));
308 return StatusCode::SUCCESS;
316 std::vector<boost::regex>::const_iterator iter;
318 if ( boost::regex_match(name,*iter) )
return true;
const boost::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)
Header file for AthHistogramAlgorithm.
virtual StatusCode initialize() override
ValgrindAuditor(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< std::string > m_algs
List of algorithms to profile.
StatusCode decodeIntervals()
unsigned int m_eventCounter
Internal event counter for BeginEvent incident.
void do_after(const std::string &name, const std::string &hook)
virtual void after(const std::string &event, const std::string &name, const EventContext &ctx, const StatusCode &sc) override
void do_before(const std::string &name, const std::string &hook)
std::vector< std::string > m_intervals
List of auditor intervals to profile.
std::pair< boost::regex, std::string > NameEvt
Typedef for algorithm/event pair, e.g. ("MyAlg","initialize")
virtual void handle(const Incident &incident) override
Incident handler.
virtual ~ValgrindAuditor()
bool algMatch(const std::string &name)
std::vector< std::pair< NameEvt, NameEvt > > m_hooks
Internal storage of intervals.
unsigned int m_ignoreFirstNEvents
Don't profile on the first N events.
bool m_dumpAfterEachInterval
Dump profile after each interval.
ServiceHandle< IValgrindSvc > m_valSvc
Handle to ValgrindSvc.
virtual void do_beforeExecute(const std::string &name)
Start callgrind instrumentation.
virtual void do_afterExecute(const std::string &name)
Stop callgrind instrumentation.
std::vector< boost::regex > m_algsRegEx
Regular expressions for algorithm name matching.
virtual void before(const std::string &event, const std::string &name, const EventContext &ctx) override