Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ValgrindSvc.cxx
Go to the documentation of this file.
1 
3 /*
4  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 // ValgrindSvc.cxx
8 // Implementation file for class ValgrindSvc
9 // Author: S.Binet<binet@cern.ch>
10 // Frank Winklmeier
12 
13 // valgrind includes
14 #include "valgrind/valgrind.h"
15 #include "valgrind/memcheck.h"
16 #include "valgrind/callgrind.h"
17 
18 // FrameWork includes
19 #include "Gaudi/Property.h"
20 #include "GaudiKernel/IIncidentSvc.h"
21 #include "GaudiKernel/Incident.h"
22 #include "GaudiKernel/ServiceHandle.h"
23 #include "GaudiKernel/Memory.h"
24 
25 // Valkyrie includes
26 #include "ValgrindSvc.h"
27 
28 
30 // Public methods:
32 
33 // Constructors
35 ValgrindSvc::ValgrindSvc( const std::string& name,
36  ISvcLocator* pSvcLocator ) :
37  base_class(name, pSvcLocator),
38  m_eventCounter(0),
39  m_profileCounter(0)
40 {
41  //
42  // Property declaration
43  //
44  declareProperty( "ProfiledAlgs", m_algs,
45  "List of profiled algorithms" );
46 
47  declareProperty( "ProfiledIntervals", m_intervals,
48  "Intervals to profile (e.g. 'MyAlg.initialize:MyAlg.finalize'" );
49 
50  declareProperty( "DumpAfterEachEvent", m_dumpAfterEachEvent = false,
51  "Dump separate profile after each event" );
52 
53  declareProperty( "DumpAfterEachInterval", m_dumpAfterEachInterval = true,
54  "Dump separate profile after each interval in ProfiledIntervals" );
55 
56  declareProperty( "DumpAfterIncident", m_dumpAfterIncident,
57  "List of incidents on which to dump a profile");
58 
59  declareProperty( "IgnoreFirstNEvents", m_ignoreFirstNEvents = 0,
60  "Do not profile the first N events");
61 }
62 
63 // Destructor
66 {}
67 
68 // Athena Algorithm's Hooks
71 {
72  ATH_MSG_DEBUG ("Initializing " << name());
73 
74  ATH_MSG_INFO ("My process ID is [" << System::procID() << "]");
75 
76  const bool insideValgrind = static_cast<bool>(RUNNING_ON_VALGRIND);
77  if ( insideValgrind ) {
78  ATH_MSG_INFO ("=== Running from inside Valgrind ! Hi there! ===");
79  }
80  else {
81  ATH_MSG_WARNING ("=== Valgrind is not running! ===");
82  }
83 
84  // Use incidents in case there is no auditor configured
85  if (!m_algs.empty() || !m_intervals.empty()) {
86 
87  // FIXME: We create the auditor here in C++ due to the lack of a
88  // configurable auditor.
89  makeAuditor("ValgrindAuditor",auditorSvc()).ignore();
90 
91  if ((auditorSvc()==0) || auditorSvc()->getAuditor("ValgrindAuditor")==0) {
92  ATH_MSG_ERROR ("Cannot find [ValgrindAuditor]. ");
93  return StatusCode::FAILURE;
94  }
95  else {
96  ATH_MSG_VERBOSE ("Found [ValgrindAuditor].");
97  }
98  }
99 
100  // Register incidents
101  ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", this->name());
102  ATH_CHECK(incSvc.retrieve());
103  incSvc->addListener( this, IncidentType::BeginEvent );
104  incSvc->addListener( this, IncidentType::EndEvent );
105 
106  for(const std::string& incident : m_dumpAfterIncident) {
107  incSvc->addListener( this, incident );
108  }
109 
110  return StatusCode::SUCCESS;
111 
112 }
113 
115 {
116  ATH_MSG_INFO ("Finalizing " << name() << "...");
117  return StatusCode::SUCCESS;
118 }
119 
121 // Const methods:
123 
125 // Non-const methods:
127 
128 void ValgrindSvc::handle( const Incident& inc )
129 {
130  // Only use Begin/EndEvent incident if no profiled algorithm or interval is set
131  bool useEventIncident = m_intervals.empty() && m_algs.empty();
132 
133  // BeginEvent
134  if ( inc.type() == IncidentType::BeginEvent ) {
135  m_eventCounter++;
136  if ( useEventIncident && m_eventCounter > m_ignoreFirstNEvents) {
137  ATH_MSG_DEBUG ("[BeginEvent] Callgrind instrumentation ON.");
139  }
140  }
141 
142  // EndEvent
143  if ( inc.type() == IncidentType::EndEvent && (m_eventCounter > m_ignoreFirstNEvents) ) {
144  if ( useEventIncident ) {
146  ATH_MSG_DEBUG ("[EndEvent] Callgrind instrumentation OFF.");
147  }
148  if ( !m_algs.empty() && m_dumpAfterEachEvent ) {
150  ATH_MSG_INFO ("Creating callgrind profile #" << profileCount()
151  << " for event #" << m_eventCounter);
152  }
153  }
154 
155  // Optional additional dumps for user specified incidents
156  if ( std::find(m_dumpAfterIncident.begin(),
157  m_dumpAfterIncident.end(),
158  inc.type()) != m_dumpAfterIncident.end() ) {
160  ATH_MSG_INFO (" Creating callgrind profile #" << profileCount()
161  << " after incident [" << inc.type() << "].");
162  }
163 
164 }
165 
166 
168 // Protected methods:
170 
172 // Const methods:
174 
176 // Non-const methods:
178 
180 {
181  CALLGRIND_START_INSTRUMENTATION;
182 }
183 
185 {
186  CALLGRIND_STOP_INSTRUMENTATION;
187 }
188 
190 {
191  CALLGRIND_TOGGLE_COLLECT;
192 }
193 
194 void ValgrindSvc::callgrindDumpStats( std::ostream& /*out*/ )
195 {
196  CALLGRIND_DUMP_STATS;
198 }
199 
201 {
202  VALGRIND_DO_LEAK_CHECK;
203 }
204 
205 
206 // Copied from PerfMonComps/PerfMonUtils
207 // Would rather create the auditor from python but couldn't make it work
208 StatusCode ValgrindSvc::makeAuditor (const std::string& audName,
209  IAuditorSvc* audSvc)
210 {
211  if ( 0 == audSvc ) {
212  ATH_MSG_ERROR ("Null pointer to IAuditorSvc !!");
213  return StatusCode::FAILURE;
214  }
215 
216  if ( 0 != audSvc->getAuditor( audName ) ) {
217  ATH_MSG_VERBOSE ("AuditorSvc already knows about ["
218  << audName << "]... good.");
219  return StatusCode::SUCCESS;
220  }
221 
222  const std::string propName = "Auditors";
223  IProperty * audSvcProp = dynamic_cast<IProperty*>(audSvc);
224 
225  if ( 0 == audSvcProp ) {
226  ATH_MSG_ERROR ("Could not dyn-cast IAuditorSvc to an IProperty !!");
227  return StatusCode::FAILURE;
228  }
229 
230  StringArrayProperty audNames;
231  audNames.assign( audSvcProp->getProperty(propName) );
232  std::vector<std::string> updatedNames( audNames.value() );
233  updatedNames.push_back( audName );
234  audNames.set( updatedNames );
235  audNames.setName( propName );
236  if ( !audSvcProp->setProperty( audNames ).isSuccess() ) {
238  ("Could not add [" << audName
239  << "] to the list of auditors of [AuditorSvc] !!"
240  << endmsg
241  << audSvcProp->getProperty(propName));
242  return StatusCode::FAILURE;
243  }
244 
245  // make sure the auditor has been created...
246  if ( 0 == audSvc->getAuditor( audName ) ) {
247  ATH_MSG_ERROR ("Failed to make AuditorSvc instantiating ["
248  << audName << "] !!");
249  return StatusCode::FAILURE;
250  }
251 
252  ATH_MSG_VERBOSE ("[" << audName << "] successfully created.");
253  return StatusCode::SUCCESS;
254 }
ValgrindSvc::m_dumpAfterIncident
std::vector< std::string > m_dumpAfterIncident
List of incidents on which to create a profile dump.
Definition: ValgrindSvc.h:104
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
ValgrindSvc::m_eventCounter
unsigned int m_eventCounter
Internal event counter for BeginEvent incident.
Definition: ValgrindSvc.h:107
ValgrindSvc::handle
virtual void handle(const Incident &incident) override
incident service handle for Begin/EndEvent
Definition: ValgrindSvc.cxx:128
ValgrindSvc::callgrindToggleCollect
virtual void callgrindToggleCollect() override
Toggle callgrind event collection.
Definition: ValgrindSvc.cxx:189
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
ValgrindSvc.h
ValgrindSvc::m_intervals
std::vector< std::string > m_intervals
List of auditor intervals to profile Syntax: "MessageSvc.initialize:MessageSvc.finalize".
Definition: ValgrindSvc.h:92
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ValgrindSvc::makeAuditor
StatusCode makeAuditor(const std::string &audName, IAuditorSvc *audSvc)
helper method to create auditors
Definition: ValgrindSvc.cxx:208
ValgrindSvc::m_dumpAfterEachInterval
bool m_dumpAfterEachInterval
Dump separate profile after each interval.
Definition: ValgrindSvc.h:98
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
ValgrindSvc::m_ignoreFirstNEvents
unsigned int m_ignoreFirstNEvents
Don't profile on the first N events.
Definition: ValgrindSvc.h:101
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ValgrindSvc::valgrindDoLeakCheck
virtual void valgrindDoLeakCheck() override
Do a leak check now.
Definition: ValgrindSvc.cxx:200
ValgrindSvc::m_dumpAfterEachEvent
bool m_dumpAfterEachEvent
Dump separate profile after each event.
Definition: ValgrindSvc.h:95
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
L1CaloPhase1Monitoring.propName
propName
Definition: L1CaloPhase1Monitoring.py:527
ValgrindSvc::callgrindStartInstrumentation
virtual void callgrindStartInstrumentation() override
Start callgrind instrumentation.
Definition: ValgrindSvc.cxx:179
ValgrindSvc::m_algs
std::vector< std::string > m_algs
List of algorithms to profile If list is empty, profile between begin/end event.
Definition: ValgrindSvc.h:88
ValgrindSvc::m_profileCounter
unsigned int m_profileCounter
Counter of created profiles.
Definition: ValgrindSvc.h:110
ValgrindSvc::ValgrindSvc
ValgrindSvc(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Definition: ValgrindSvc.cxx:35
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
ValgrindSvc::~ValgrindSvc
virtual ~ValgrindSvc()
Destructor:
Definition: ValgrindSvc.cxx:65
ValgrindSvc::initialize
virtual StatusCode initialize() override
Gaudi Service Implementation.
Definition: ValgrindSvc.cxx:70
ValgrindSvc::callgrindStopInstrumentation
virtual void callgrindStopInstrumentation() override
Stop callgrind instrumentation.
Definition: ValgrindSvc.cxx:184
ValgrindSvc::finalize
virtual StatusCode finalize() override
Definition: ValgrindSvc.cxx:114
ValgrindSvc::callgrindDumpStats
virtual void callgrindDumpStats(std::ostream &out) override
Dump callgrind profiling stats.
Definition: ValgrindSvc.cxx:194
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
ServiceHandle< IIncidentSvc >
ValgrindSvc::profileCount
virtual unsigned int profileCount() override
Number of created callgrind profiles.
Definition: ValgrindSvc.h:69