The Gaudi Framework  master (bdbe7744)
Loading...
Searching...
No Matches
TimelineSvc.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2026 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 "TimelineSvc.h"
15
16#include <algorithm>
17#include <fstream>
18#include <ranges>
19
22 if ( !sc.isSuccess() ) return sc;
23
24 if ( msgLevel( MSG::DEBUG ) ) debug() << "initialize" << endmsg;
25
26 m_events.clear();
27 // the initial allocation of tbb::concurrent_vector determines the size of
28 // the first allocated array, useful to reduce fragmentation
29 m_events.reserve( 1024 );
30
31 if ( m_partial ) {
32 std::ofstream out( m_timelineFile + ".part", std::ofstream::trunc | std::ofstream::out );
33 out << "#start end algorithm thread slot event" << std::endl;
34 out.close();
35 }
36
38}
39
41
42 MsgStream log( msgSvc(), name() );
43 log << MSG::DEBUG << "reinitialize" << endmsg;
44
45 m_events.clear();
46
48}
49
51 if ( m_dumpTimeline && m_events.size() > 0 ) {
52 MsgStream log( msgSvc(), name() );
53
54 log << MSG::INFO << "Outputting timeline with " << m_events.size() << " entries to file " << m_timelineFile.value()
55 << endmsg;
56
58 }
59
61}
62
64 auto& newTimelineEvent = m_events.emplace( std::make_tuple( alg, ctx.evt() ), TimelineEvent{} ).first->second;
65 newTimelineEvent.algorithm = std::move( alg );
66 newTimelineEvent.slot = ctx.slot();
67 newTimelineEvent.event = ctx.evt();
68 TimelineRecorder recorder{ newTimelineEvent };
69 if ( m_partial ) {
70 std::ofstream out( m_timelineFile + ".part", std::ofstream::app | std::ofstream::out );
71 out << std::chrono::duration_cast<std::chrono::nanoseconds>( newTimelineEvent.start.time_since_epoch() ).count()
72 << " "
73 << std::chrono::duration_cast<std::chrono::nanoseconds>( newTimelineEvent.end.time_since_epoch() ).count()
74 << " " << newTimelineEvent.algorithm << " " << newTimelineEvent.thread << " " << newTimelineEvent.slot << " "
75 << newTimelineEvent.event << std::endl;
76
77 out.close();
78 }
79 return recorder;
80}
81
83
85 auto [begin, end] = m_events.equal_range( std::make_tuple( e.algorithm, e.event ) );
86 if ( begin == end ) { return false; }
87 auto it =
88 std::min_element( begin, end, []( const auto& a, const auto& b ) { return a.second.start < b.second.start; } );
89 e = it->second;
90 return true;
91}
92
94 auto [begin, end] = m_events.equal_range( std::make_tuple( e.algorithm, e.event ) );
95 if ( begin == end ) { return false; }
96 auto it =
97 std::max_element( begin, end, []( const auto& a, const auto& b ) { return a.second.start < b.second.start; } );
98 e = it->second;
99 return true;
100}
101
103 std::ofstream out( m_timelineFile, std::ofstream::out | std::ofstream::trunc );
104
105 out << "#start end algorithm thread slot event" << std::endl;
106
107 auto flat_events = std::vector<TimelineEvent>();
108 flat_events.reserve( m_events.size() );
109
110 std::ranges::copy( m_events | std::views::values, std::back_inserter( flat_events ) );
111
112 std::sort( flat_events.begin(), flat_events.end(), []( const auto& a, const auto& b ) { return a.start < b.start; } );
113 for ( const auto& e : flat_events ) {
114 out << std::chrono::duration_cast<std::chrono::nanoseconds>( e.start.time_since_epoch() ).count() << " "
115 << std::chrono::duration_cast<std::chrono::nanoseconds>( e.end.time_since_epoch() ).count() << " "
116 << e.algorithm << " " << e.thread << " " << e.slot << " " << e.event << std::endl;
117 }
118
119 out.close();
120}
121
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define DECLARE_COMPONENT(type)
const SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
This class represents an entry point to all the event specific data.
RAII helper to record timeline events.
Definition of the MsgStream class used to transmit messages.
Definition MsgStream.h:29
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
StatusCode initialize() override
Definition Service.cpp:118
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isSuccess() const
Definition StatusCode.h:302
constexpr static const auto SUCCESS
Definition StatusCode.h:99
Gaudi::Property< bool > m_partial
Definition TimelineSvc.h:42
void outputTimeline()
bool getTimelineEvent(TimelineEvent &) const override
StatusCode initialize() override
StatusCode reinitialize() override
bool getFirstMatching(TimelineEvent &) const override
StatusCode finalize() override
Gaudi::Property< std::string > m_timelineFile
Definition TimelineSvc.h:39
TimelineRecorder getRecorder(std::string alg, const EventContext &ctx) override
Gaudi::Property< bool > m_dumpTimeline
Definition TimelineSvc.h:41
bool getLastMatching(TimelineEvent &) const override
tbb::concurrent_unordered_multimap< key_type, TimelineEvent, boost::hash< key_type > > m_events
Definition TimelineSvc.h:45
@ DEBUG
Definition IMessageSvc.h:22
@ INFO
Definition IMessageSvc.h:22
std::string algorithm