ATLAS Offline Software
Loading...
Searching...
No Matches
TrigCostSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
8
9#include "TrigCostSvc.h"
10
11#include <mutex> // For std::unique_lock
12
14
15TrigCostSvc::TrigCostSvc(const std::string& name, ISvcLocator* pSvcLocator) :
16base_class(name, pSvcLocator), // base_class = AthService
26{
27 ATH_MSG_DEBUG("TrigCostSvc regular constructor");
28}
29
30// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
31
33 // delete[] m_eventMonitored;
34 ATH_MSG_DEBUG("TrigCostSvc destructor()");
35}
36
37// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
38
39
41 ATH_MSG_DEBUG("TrigCostSvc initialize()");
43 // TODO Remove this when the configuration is correctly propagated in config-then-run jobs
44 if (!m_eventSlots) {
45 ATH_MSG_WARNING("numConcurrentEvents() == 0. This is a misconfiguration, probably coming from running from pickle. "
46 "Setting local m_eventSlots to a 'large' number until this is fixed to allow the job to proceed.");
47 m_eventSlots = 100;
48 }
49 ATH_MSG_INFO("Initializing TrigCostSvc with " << m_eventSlots << " event slots");
50
51 // We cannot have a vector here as atomics are not movable nor copyable. Unique heap arrays are supported by C++
52 m_eventMonitored = std::make_unique< std::atomic<bool>[] >( m_eventSlots );
53 m_slotMutex = std::make_unique< std::shared_mutex[] >( m_eventSlots );
54
55 for (size_t i = 0; i < m_eventSlots; ++i) m_eventMonitored[i] = false;
56
59
60 return StatusCode::SUCCESS;
61}
62
63// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
64
66 ATH_MSG_DEBUG("TrigCostSvc finalize()");
67 if (m_saveHashes) {
69 ATH_MSG_INFO("Calling hashes2file, saving dump of job's HLT hashing dictionary to disk.");
70 }
71 return StatusCode::SUCCESS;
72}
73
74// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
75
76StatusCode TrigCostSvc::startEvent(const EventContext& context, const bool enableMonitoring) {
77 const bool monitoredEvent = (enableMonitoring || m_monitorAllEvents);
78 ATH_CHECK(checkSlot(context));
79
80 m_eventMonitored[ context.slot() ] = false;
81
82 {
83 // "clear" is a whole table operation, we need it all to ourselves
84 std::unique_lock lockUnique( m_slotMutex[ context.slot() ] );
85 if (monitoredEvent) {
86 // Empty transient thread-safe stores in preparation for recording this event's cost data
87 ATH_CHECK(m_algStartInfo.clear(context, msg()));
88 ATH_CHECK(m_algStopTime.clear(context, msg()));
89 }
90
91 // Enable collection of data in this slot for monitoredEvents
92 m_eventMonitored[ context.slot() ] = monitoredEvent;
93 }
94
95 // As we missed the AuditType::Before of the TrigCostSupervisorAlg (which is calling this TrigCostSvc::startEvent), let's add it now.
96 // This will be our canonical initial timestamps for measuring this event. Similar will be done for DecisionSummaryMakerAlg at the end
97 ATH_CHECK(processAlg(context, m_costSupervisorAlgName, AuditType::Before));
98
99 return StatusCode::SUCCESS;
100}
101
102// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
103
104StatusCode TrigCostSvc::processAlg(const EventContext& context, const std::string& caller, const AuditType type) {
105 ATH_CHECK(checkSlot(context));
106
107 TrigTimeStamp now;
108
109 // Do per-event within-slot monitoring
110 if (m_eventMonitored[ context.slot() ]) {
111 // Multiple simultaneous calls allowed here, adding their data to the concurrent map.
112 std::shared_lock lockShared( m_slotMutex[ context.slot() ] );
113
115 ATH_CHECK( ai.isValid() );
116
117 ATH_CHECK(monitor(context, ai, now, type));
118
119 ATH_MSG_VERBOSE("Caller '" << caller << "', '" << ai.m_store << "', slot:" << context.slot() << " "
120 << (type == AuditType::Before ? "BEGAN" : "ENDED") << " at " << now.microsecondsSinceEpoch());
121 }
122
123 // MultiSlot mode: do per-event monitoring of all slots, but saving the data within the master-slot
124 if (m_enableMultiSlot && context.slot() != m_masterSlot && m_eventMonitored[ m_masterSlot ]) {
125 std::shared_lock lockShared( m_slotMutex[ m_masterSlot ] );
126
127 // Note: we override the storage location of these data from all other slots to be saved in the MasterSlot
129 ATH_CHECK( ai.isValid() );
130
131 ATH_CHECK(monitor(context, ai, now, type));
132 }
133
134 return StatusCode::SUCCESS;
135}
136
137// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
138
139StatusCode TrigCostSvc::monitor(const EventContext& context, const AlgorithmIdentifier& ai, const TrigTimeStamp& now, const AuditType type) {
140
141 if (type == AuditType::Before) {
142
144 now,
145 std::this_thread::get_id(),
146 getROIID(context),
147 static_cast<uint32_t>(context.slot())
148 };
149 ATH_CHECK( m_algStartInfo.insert(ai, ap, msg()) );
150
151 // Cache the AlgorithmIdentifier which has just started executing on this thread
152 if (ai.m_realSlot == ai.m_slotToSaveInto) {
153 tbb::concurrent_hash_map<std::thread::id, AlgorithmIdentifier, ThreadHashCompare>::accessor acc;
154 m_threadToAlgMap.insert(acc, ap.m_algThreadID);
155 acc->second = ai;
156 }
157
158 } else if (type == AuditType::After) {
159
160 ATH_CHECK( m_algStopTime.insert(ai, now, msg()) );
161
162 } else {
163
164 ATH_MSG_ERROR("Only expecting AuditType::Before or AuditType::After");
165 return StatusCode::FAILURE;
166
167 }
168
169 return StatusCode::SUCCESS;
170}
171
172// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
173
174StatusCode TrigCostSvc::endEvent(const EventContext& context, SG::WriteHandle<xAOD::TrigCompositeContainer>& costOutputHandle) {
175 ATH_CHECK(checkSlot(context));
176 if (m_eventMonitored[ context.slot() ] == false) {
177 // This event was not monitored - nothing to do.
178 ATH_MSG_DEBUG("Not a monitored event.");
179 return StatusCode::SUCCESS;
180 }
181
182 // As we will miss the AuditType::After of the TrigCostFinalizeAlg (which is calling this TrigCostSvc::endEvent), let's add it now.
183 // This will be our canonical final timestamps for measuring this event. Similar was done for HLTSeeding at the start
184 ATH_CHECK(processAlg(context, m_costFinalizeAlgName, AuditType::After));
185
186 // Reset eventMonitored flags
187 m_eventMonitored[ context.slot() ] = false;
188
189 // Now that this atomic is set to FALSE, additional algs in this instance which trigger this service will
190 // not be able to call TrigCostSvc::monitor
191
192 // ... but processAlg might already be running in other threads...
193 // Wait to obtain an exclusive lock.
194 std::unique_lock lockUnique( m_slotMutex[ context.slot() ] );
195
196 // we can now perform whole-map inspection of this event's TrigCostDataStores without the danger that it will be changed further
197
198 // Let's start by getting the global STOP time we just wrote
199 uint64_t eventStopTime = 0;
200 {
202 ATH_CHECK( myAi.isValid() );
203 tbb::concurrent_hash_map<AlgorithmIdentifier, TrigTimeStamp, AlgorithmIdentifierHashCompare>::const_accessor stopTimeAcessor;
204 if (m_algStopTime.retrieve(myAi, stopTimeAcessor, msg()).isFailure()) {
205 ATH_MSG_ERROR("No end time for '" << myAi.m_caller << "', '" << myAi.m_store << "'"); // Error as we JUST entered this info!
206 } else { // retrieve was a success
207 //coverity[FORWARD_NULL:FALSE]
208 eventStopTime = stopTimeAcessor->second.microsecondsSinceEpoch();
209 }
210 }
211
212 // And the global START time for the event
213 uint64_t eventStartTime = 0;
214 {
216 ATH_CHECK( hltSeedingAi.isValid() );
217 tbb::concurrent_hash_map<AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_accessor startAcessor;
218 if (m_algStartInfo.retrieve(hltSeedingAi, startAcessor, msg()).isFailure()) {
219 ATH_MSG_ERROR("No alg info for '" << hltSeedingAi.m_caller << "', '" << hltSeedingAi.m_store << "'"); // Error as we know this info must be present
220 } else { // retrieve was a success
221 //coverity[FORWARD_NULL:FALSE]
222 eventStartTime = startAcessor->second.m_algStartTime.microsecondsSinceEpoch();
223 }
224 }
225
226 // Read payloads. Write to persistent format
227 tbb::concurrent_hash_map< AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_iterator beginIt;
228 tbb::concurrent_hash_map< AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_iterator endIt;
229 tbb::concurrent_hash_map< AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_iterator it;
230 ATH_CHECK(m_algStartInfo.getIterators(context, msg(), beginIt, endIt));
231
232 ATH_MSG_DEBUG("Monitored event with " << std::distance(beginIt, endIt) << " AlgorithmPayload objects.");
233
234 std::map<size_t, size_t> aiToHandleIndex;
235 for (it = beginIt; it != endIt; ++it) {
236 const AlgorithmIdentifier& ai = it->first;
237 const AlgorithmPayload& ap = it->second;
238 uint64_t startTime = ap.m_algStartTime.microsecondsSinceEpoch();
239
240 // Can we find the end time for this alg? If not, it is probably still running. Hence we use "now" as the default time.
241 uint64_t stopTime = eventStopTime;
242 {
243 tbb::concurrent_hash_map<AlgorithmIdentifier, TrigTimeStamp, AlgorithmIdentifierHashCompare>::const_accessor stopTimeAcessor;
244 if (m_algStopTime.retrieve(ai, stopTimeAcessor, msg()).isFailure()) {
245 ATH_MSG_DEBUG("No end time for '" << ai.m_caller << "', '" << ai.m_store << "'");
246 } else { // retrieve was a success
247 stopTime = stopTimeAcessor->second.microsecondsSinceEpoch();
248 }
249 // stopTimeAcessor goes out of scope - lock released
250 }
251
252 // It is possible (when in the master-slot) to catch just the END of an Alg's exec from another slot, and then the START of the same
253 // alg executing in the next event in that same other-slot.
254 // This gives us an end time which is before the start time. Disregard these entries.
255 if (startTime > stopTime) {
256 ATH_MSG_VERBOSE("Disregard start-time:" << startTime << " > stop-time:" << stopTime
257 << " for " << TrigConf::HLTUtils::hash2string( ai.callerHash(msg()), "ALG") << " in slot " << ap.m_slot << ", this is slot " << context.slot());
258 continue;
259 }
260
261 // Lock the start and stop times to be no later than eventStopTime.
262 // E.g. it's possible for an alg in another slot to start or stop running after 'processAlg(context, m_costFinalizeAlgName, AuditType::After))'
263 // but before 'lockUnique( m_slotMutex[ context.slot() ] )', creating a timestamp after the nominal end point for this event.
264 // If the alg starts afterwards, we disregard it in lieu of setting to have zero walltime.
265 // If the alg stops afterwards, we truncate its stop time to be no later than eventStopTime
266 if (startTime > eventStopTime) {
267 ATH_MSG_VERBOSE("Disregard " << TrigConf::HLTUtils::hash2string( ai.callerHash(msg()), "ALG") << " as it started after endEvent() was finished being called" );
268 continue;
269 }
270 if (stopTime > eventStopTime) {
271 ATH_MSG_VERBOSE(TrigConf::HLTUtils::hash2string( ai.callerHash(msg()), "ALG") << " stopped after endEvent() was called, but before the cost container was locked,"
272 << " truncating its ending time stamp from " << stopTime << " to " << eventStopTime);
273 stopTime = eventStopTime;
274 }
275
276 // Do the same, locking the start and stop times to be no earlier than eventStartTime
277 // If the alg stops before eventStartTime, we disregard it in lieu of setting it to have zero walltime
278 // If the alg starts before eventStartTime, we truncate its start time to be no later than eventStopTime
279 if (stopTime < eventStartTime) {
280 ATH_MSG_VERBOSE("Disregard " << TrigConf::HLTUtils::hash2string( ai.callerHash(msg()), "ALG") << " as it stopped before startEvent() was finished being called" );
281 continue;
282 }
283 if (startTime < eventStartTime) {
284 ATH_MSG_VERBOSE(TrigConf::HLTUtils::hash2string( ai.callerHash(msg()), "ALG") << " started just after the cost container was unlocked, but before the HLTSeeding record was written."
285 << " truncating its starting time stamp from " << startTime << " to " << eventStartTime);
286 startTime = eventStartTime;
287 }
288
289 // Make a new TrigComposite to persist monitoring payload for this alg
291 costOutputHandle->push_back( tc );
292 // tc is now owned by storegate and, and has an aux store provided by the TrigCompositeCollection
293
294 const uint32_t threadID = static_cast<uint32_t>( std::hash< std::thread::id >()(ap.m_algThreadID) );
295 uint32_t threadEnumerator = 0;
296 {
297 // We can have multiple slots get here at the same time
298 std::lock_guard<std::mutex> lock(m_globalMutex);
299 const std::unordered_map<uint32_t, uint32_t>::const_iterator mapIt = m_threadToCounterMap.find(threadID);
300 if (mapIt == m_threadToCounterMap.end()) {
301 threadEnumerator = m_threadCounter;
302 m_threadToCounterMap.insert( std::make_pair(threadID, m_threadCounter++) );
303 } else {
304 threadEnumerator = mapIt->second;
305 }
306 }
307
308 bool result = true;
309 result &= tc->setDetail("alg", ai.callerHash(msg()));
310 result &= tc->setDetail("store", ai.storeHash(msg()));
311 result &= tc->setDetail("view", ai.m_viewID);
312 result &= tc->setDetail("thread", threadEnumerator);
313 result &= tc->setDetail("thash", threadID);
314 result &= tc->setDetail("slot", ap.m_slot);
315 result &= tc->setDetail("roi", ap.m_algROIID);
316 result &= tc->setDetail("start", startTime);
317 result &= tc->setDetail("stop", stopTime);
318 if (!result) ATH_MSG_WARNING("Failed to append one or more details to trigger cost TC");
319
320 aiToHandleIndex[ai.m_hash] = costOutputHandle->size() - 1;
321 }
322
323 if (msg().level() <= MSG::VERBOSE) {
324 ATH_MSG_VERBOSE("--- Trig Cost Event Summary ---");
325 for ( const xAOD::TrigComposite* tc : *costOutputHandle ) {
326 ATH_MSG_VERBOSE("Algorithm:'" << TrigConf::HLTUtils::hash2string( tc->getDetail<TrigConf::HLTHash>("alg"), "ALG") << "'");
327 ATH_MSG_VERBOSE(" Store:'" << TrigConf::HLTUtils::hash2string( tc->getDetail<TrigConf::HLTHash>("store"), "STORE") << "'");
328 ATH_MSG_VERBOSE(" View ID:" << tc->getDetail<int16_t>("view"));
329 ATH_MSG_VERBOSE(" Thread #:" << tc->getDetail<uint32_t>("thread") );
330 ATH_MSG_VERBOSE(" Thread ID Hash:" << tc->getDetail<uint32_t>("thash") );
331 ATH_MSG_VERBOSE(" Slot:" << tc->getDetail<uint32_t>("slot") );
332 ATH_MSG_VERBOSE(" RoI ID Hash:" << tc->getDetail<int32_t>("roi") );
333 ATH_MSG_VERBOSE(" Start Time:" << tc->getDetail<uint64_t>("start") << " mu s");
334 ATH_MSG_VERBOSE(" Stop Time:" << tc->getDetail<uint64_t>("stop") << " mu s");
335 }
336 }
337
338 return StatusCode::SUCCESS;
339}
340
341// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
342
343StatusCode TrigCostSvc::generateTimeoutReport(const EventContext& context, std::string& report) {
344
345 ATH_CHECK(checkSlot(context));
346 if (!m_eventMonitored[context.slot()]) {
347 ATH_MSG_DEBUG("Not a monitored event.");
348 report = "";
349 return StatusCode::SUCCESS;
350 }
351
352 std::unique_lock lockUnique(m_slotMutex[context.slot()]);
353
354 tbb::concurrent_hash_map< AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_iterator beginIt;
355 tbb::concurrent_hash_map< AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_iterator endIt;
356 tbb::concurrent_hash_map< AlgorithmIdentifier, AlgorithmPayload, AlgorithmIdentifierHashCompare>::const_iterator it;
357 ATH_CHECK(m_algStartInfo.getIterators(context, msg(), beginIt, endIt));
358
359 // Create map that sorts in descending order
360 std::map<uint64_t, std::string, std::greater<uint64_t>> timeToAlgMap;
361
362 for (it = beginIt; it != endIt; ++it) {
363 const AlgorithmIdentifier& ai = it->first;
364 const AlgorithmPayload& ap = it->second;
365
366 // Don't look at any records from other slots
367 if (ai.m_realSlot != context.slot()) continue;
368
369 uint64_t startTime = ap.m_algStartTime.microsecondsSinceEpoch();
370 uint64_t stopTime = 0;
371 {
372 tbb::concurrent_hash_map<AlgorithmIdentifier, TrigTimeStamp, AlgorithmIdentifierHashCompare>::const_accessor stopTimeAcessor;
373 if (m_algStopTime.retrieve(ai, stopTimeAcessor, msg()).isFailure()) {
374 ATH_MSG_DEBUG("No end time for '" << ai.m_caller << "', '" << ai.m_store << "'");
375 } else { // retrieve was a success
376 //coverity[FORWARD_NULL:FALSE]
377 stopTime = stopTimeAcessor->second.microsecondsSinceEpoch();
378 }
379 // stopTimeAcessor goes out of scope - lock released
380 }
381
382 if (stopTime == 0) continue;
383
384 timeToAlgMap[stopTime-startTime] = ai.m_caller;
385 }
386
387 // Save top 5 times to the report
388 report = "Timeout detected with the following algorithms consuming the most time: ";
389 int algCounter = 0;
390 for(const std::pair<const uint64_t, std::string>& p : timeToAlgMap){
391 // Save time in miliseconds instead of microseconds
392 report += p.second + " (" + std::to_string(std::lround(p.first/1e3)) + " ms)";
393 ++algCounter;
394 if (algCounter >= 5){
395 break;
396 }
397 report += ", ";
398 }
399
400 return StatusCode::SUCCESS;
401}
402
403// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
404
405StatusCode TrigCostSvc::discardEvent(const EventContext& context) {
406
407 if (m_monitorAllEvents) {
408 ATH_MSG_DEBUG("All events are monitored - event will not be discarded");
409 return StatusCode::SUCCESS;
410 }
411
412 ATH_MSG_DEBUG("Cost Event will be discarded");
413 ATH_CHECK(checkSlot(context));
414 {
415 std::unique_lock lockUnique( m_slotMutex[ context.slot() ] );
416
417 // Reset eventMonitored flags
418 m_eventMonitored[ context.slot() ] = false;
419
420 // tables are cleared at the start of the event
421 }
422 return StatusCode::SUCCESS;
423}
424
425// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
426
427StatusCode TrigCostSvc::checkSlot(const EventContext& context) const {
428 if (context.slot() >= m_eventSlots) {
429 ATH_MSG_FATAL("Job is using event slot #" << context.slot() << ", but we only reserved space for: " << m_eventSlots);
430 return StatusCode::FAILURE;
431 }
432 return StatusCode::SUCCESS;
433}
434
435// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
436
437int32_t TrigCostSvc::getROIID(const EventContext& context) {
438 if (Atlas::hasExtendedEventContext(context)) {
440 if (roi) return static_cast<int32_t>(roi->roiId());
441 }
443}
444
445// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
446
447bool TrigCostSvc::isMonitoredEvent(const EventContext& context, const bool includeMultiSlot) const {
448 if (m_eventMonitored[ context.slot() ]) {
449 return true;
450 }
451 if (includeMultiSlot && m_enableMultiSlot) {
453 }
454 return false;
455}
456
457// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
458
459size_t TrigCostSvc::ThreadHashCompare::hash(const std::thread::id& thread) {
460 return static_cast<size_t>( std::hash< std::thread::id >()(thread) );
461}
462
463// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
464
465bool TrigCostSvc::ThreadHashCompare::equal(const std::thread::id& x, const std::thread::id& y) {
466 return (x == y);
467}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
Maintain a set of objects, one per slot.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t tc
#define y
#define x
const IRoiDescriptor * roiDescriptor() const
Get cached pointer to View's Region of Interest Descriptor or nullptr if not describing a View.
Describes the API of the Region of Ineterest geometry.
virtual unsigned int roiId() const =0
identifiers
static void hashes2file(const std::string &fileName="hashes2string.txt")
debugging output of internal dictionary
static const std::string hash2string(HLTHash, const std::string &category=s_defaultCategory)
hash function translating identifiers into names (via internal dictionary)
virtual StatusCode processAlg(const EventContext &context, const std::string &caller, const AuditType type) override
Implementation of ITrigCostSvc::processAlg.
Gaudi::Property< bool > m_monitorAllEvents
Gaudi::Property< bool > m_saveHashes
Gaudi::Property< std::string > m_costFinalizeAlgName
std::mutex m_globalMutex
Used to protect all-slot modifications.
TrigCostDataStore< AlgorithmPayload > m_algStartInfo
Thread-safe store of algorithm start payload.
StatusCode checkSlot(const EventContext &context) const
Sanity check that the job is respecting the number of slots which were declared at config time.
TrigCostDataStore< TrigTimeStamp > m_algStopTime
Thread-safe store of algorithm stop times.
Gaudi::Property< bool > m_enableMultiSlot
virtual StatusCode initialize() override
Initialise, create enough storage to store m_eventSlots.
size_t m_eventSlots
Number of concurrent processing slots.
virtual ~TrigCostSvc()
Destructor.
std::unique_ptr< std::shared_mutex[] > m_slotMutex
Used to control and protect whole-table operations.
virtual bool isMonitoredEvent(const EventContext &context, const bool includeMultiSlot=true) const override
std::unique_ptr< std::atomic< bool >[] > m_eventMonitored
Used to cache if the event in a given slot is being monitored.
int32_t getROIID(const EventContext &context)
@breif Internal function to return a RoI from an extended event context context
virtual StatusCode discardEvent(const EventContext &context) override
Discard a cost monitored event.
Gaudi::Property< std::string > m_costSupervisorAlgName
TrigCostSvc(const std::string &name, ISvcLocator *pSvcLocator)
Standard ATLAS Service constructor.
Gaudi::Property< size_t > m_masterSlot
virtual StatusCode finalize() override
Finalize, act on m_saveHashes.
virtual StatusCode generateTimeoutReport(const EventContext &context, std::string &report) override
StatusCode monitor(const EventContext &context, const AlgorithmIdentifier &ai, const TrigTimeStamp &now, const AuditType type)
Internal call to save monitoring data for a given AlgorithmIdentifier.
size_t m_threadCounter
Count how many unique thread ID we have seen.
tbb::concurrent_hash_map< std::thread::id, AlgorithmIdentifier, ThreadHashCompare > m_threadToAlgMap
Keeps track of what is running right now in each thread.
virtual StatusCode endEvent(const EventContext &context, SG::WriteHandle< xAOD::TrigCompositeContainer > &costOutputHandle) override
Implementation of ITrigCostSvc::endEvent.
std::unordered_map< uint32_t, uint32_t > m_threadToCounterMap
Map thread's hash ID to a counting numeral.
virtual StatusCode startEvent(const EventContext &context, const bool enableMonitoring=true) override
Implementation of ITrigCostSvc::startEvent.
utility class to measure time duration in AthenaMT The pattern when it is useful: AlgA tags the begin...
const ExtendedEventContext & getExtendedEventContext(const EventContext &ctx)
Retrieve an extended context from a context object.
bool hasExtendedEventContext(const EventContext &ctx)
Test whether a context object has an extended context installed.
size_t getNSlots()
Return the number of event slots.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.
static AlgorithmIdentifier make(const EventContext &context, const std::string &caller, MsgStream &msg, const int16_t slotOverride=-1)
Construct an AlgorithmIdentifier.
Small structure to hold an algorithm's name and store, plus some details on its EventView.
std::string m_caller
Name of the algorithm.
std::string m_store
Name of the algorithm's store.
TrigConf::HLTHash callerHash(MsgStream &msg) const
size_t m_slotToSaveInto
The slot which is used for the purposes of recording data on this algorithm's execution.
static constexpr int16_t s_noView
Constant value used to express an Algorithm which is not running in a View.
TrigConf::HLTHash storeHash(MsgStream &msg) const
size_t m_realSlot
The actual slot of the algorithm.
size_t m_hash
Hash of algorithm + store + realSlot.
StatusCode isValid() const
int16_t m_viewID
If not within an event view, then the m_iewID = s_noView = -1.
Small structure wrap the various values stored for an algorithm just before it starts to execute.
static bool equal(const std::thread::id &x, const std::thread::id &y)
static size_t hash(const std::thread::id &thread)
MsgStream & msg
Definition testRead.cxx:32