HOPS
HOPS class reference
MHO_Profiler.hh
Go to the documentation of this file.
1 #ifndef MHO_Profiler_HH__
2 #define MHO_Profiler_HH__
3 
4 #include <cstdlib>
5 #include <cstring>
6 #include <iostream>
7 #include <mutex>
8 #include <string>
9 #include <thread>
10 #include <vector>
11 
12 #include "MHO_SelfName.hh"
13 #include "MHO_Timer.hh"
14 
15 //this define is passed in the compiler flags
16 //#define HOPS_USE_PROFILER
17 
18 namespace hops
19 {
20 
35 namespace sn = selfname;
36 
37 enum MHO_ProfilerFlag : int
38 {
39  pStartFlag = 1, //start time for this segment
40  pStopFlag = 2 //stop timer for this segment
41 };
42 
43 //short hand aliases
46 
47 using hops::pStart;
48 using hops::pStop;
49 
50 #define PROFILE_INFO_LEN 128
51 
56 {
57  int fFlag; //indicates start/stop
58  int fLineNumber; //line number of the file
59  uint64_t fThreadID;
60  double fTime;
61  char fFilename[PROFILE_INFO_LEN]; //truncated filename
62  char fFuncname[PROFILE_INFO_LEN]; //truncated function name
63 };
64 
69 {
70 
71  public:
72  //since this is a singleton we need to remove ability to copy/move
73  MHO_Profiler(MHO_Profiler const&) = delete;
75  MHO_Profiler& operator=(MHO_Profiler const&) = delete;
77 
85  {
86  static MHO_Profiler instance;
87  return instance;
88  }
89 
93  void Enable() { fDisabled = false; };
94 
98  void Disable() { fDisabled = true; };
99 
105  bool IsEnabled() const { return !fDisabled; }
106 
115  void Lock() { fMutex.lock(); };
116 
120  void Unlock() { fMutex.unlock(); };
121 
131  void AddEntry(int flag, uint64_t thread_id, std::string filename, int line_num, std::string func_name);
132 
138  void GetEvents(std::vector< MHO_ProfileEvent >& events) { events = fEvents; }
139 
143  void DumpEvents();
144 
145  private:
146  MHO_Profiler(): fNThreads(1)
147  {
148  fDisabled = true; //disabled by default
149  fEvents.reserve(1000);
150  fTimer.Start();
151  };
152 
153  virtual ~MHO_Profiler(){};
154 
155  std::mutex fMutex;
156  std::size_t fNThreads;
157  bool fDisabled;
158 
159  //map each thread to a vector of events
160  // std::vector< std::vector< MHO_ProfileEvent > > fThreadEvents;
161  std::vector< MHO_ProfileEvent > fEvents;
162 
163  MHO_Timer fTimer;
164 };
165 
166 #ifdef HOPS_USE_PROFILER
167 
168  //abuse do-while for multiline macros
169  #define profiler_start() \
170  do \
171  { \
172  MHO_Profiler::GetInstance().Lock(); \
173  MHO_Profiler::GetInstance().AddEntry(pStart, std::hash< std::thread::id >{}(std::this_thread::get_id()), \
174  std::string(sn::file_basename(__FILE__)), __LINE__, \
175  std::string(__PRETTY_FUNCTION__)); \
176  MHO_Profiler::GetInstance().Unlock(); \
177  } \
178  while(0)
179 
180  #define profiler_stop() \
181  do \
182  { \
183  MHO_Profiler::GetInstance().Lock(); \
184  MHO_Profiler::GetInstance().AddEntry(pStop, std::hash< std::thread::id >{}(std::this_thread::get_id()), \
185  std::string(sn::file_basename(__FILE__)), __LINE__, \
186  std::string(__PRETTY_FUNCTION__)); \
187  MHO_Profiler::GetInstance().Unlock(); \
188  } \
189  while(0)
190 
191 // RAII guard: calls profiler_start() on construction and profiler_stop() on destruction.
192 // __FILE__, __LINE__, __PRETTY_FUNCTION__ are captured by the macro at the call site
193 // so they reflect the enclosing function, not the guard class itself.
194 struct MHO_ProfilerGuard
195 {
196  MHO_ProfilerGuard(uint64_t thread_id, std::string filename, int line_num, std::string funcname)
197  : fThreadID(thread_id), fFilename(std::move(filename)), fFuncname(std::move(funcname))
198  {
200  MHO_Profiler::GetInstance().AddEntry(pStart, fThreadID, fFilename, line_num, fFuncname);
202  }
203 
204  ~MHO_ProfilerGuard()
205  {
207  MHO_Profiler::GetInstance().AddEntry(pStop, fThreadID, fFilename, 0, fFuncname);
209  }
210 
211  // non-copyable, non-movable
212  MHO_ProfilerGuard(const MHO_ProfilerGuard&) = delete;
213  MHO_ProfilerGuard& operator=(const MHO_ProfilerGuard&) = delete;
214 
215  private:
216  uint64_t fThreadID;
217  std::string fFilename;
218  std::string fFuncname;
219 };
220 
221  // Helper macros for token-pasting to generate unique variable names
222  #define PROFILER_CONCAT_(a, b) a##b
223  #define PROFILER_CONCAT(a, b) PROFILER_CONCAT_(a, b)
224 
225  // Declare a scope-guard that automatically records start/stop for the enclosing function.
226  // Place once at the top of any function body to profile the entire function.
227  #define profiler_scope() \
228  hops::MHO_ProfilerGuard PROFILER_CONCAT(_pg_, __LINE__)(std::hash< std::thread::id >{}(std::this_thread::get_id()), \
229  std::string(sn::file_basename(__FILE__)), __LINE__, \
230  std::string(__PRETTY_FUNCTION__))
231 
232 #else
233 
234  //profiling is not turned on, ifdef out of compilation
235  #define profiler_start()
236  #define profiler_stop()
237  #define profiler_scope()
238 
239 #endif
240 
241 } // namespace hops
242 
243 #endif
#define PROFILE_INFO_LEN
Definition: MHO_Profiler.hh:50
constexpr to strip path prefix from FILE macros
Class MHO_Profiler - uses the singleton pattern.
Definition: MHO_Profiler.hh:69
bool IsEnabled() const
Checks if the feature is enabled.
Definition: MHO_Profiler.hh:105
void Unlock()
Releases control of the mutex.
Definition: MHO_Profiler.hh:120
static MHO_Profiler & GetInstance()
provide public access to the only static instance
Definition: MHO_Profiler.hh:84
MHO_Profiler(MHO_Profiler const &)=delete
void Enable()
Sets the enabled state to true.
Definition: MHO_Profiler.hh:93
void AddEntry(int flag, uint64_t thread_id, std::string filename, int line_num, std::string func_name)
Adds a profiling event to the internal list if not disabled.
Definition: MHO_Profiler.cc:6
void GetEvents(std::vector< MHO_ProfileEvent > &events)
Getter for events - at end of program, retrieve and utilize the profiler events.
Definition: MHO_Profiler.hh:138
MHO_Profiler(MHO_Profiler &&)=delete
void Disable()
Sets HOPS_COLOR_MSG to disabled state.
Definition: MHO_Profiler.hh:98
MHO_Profiler & operator=(MHO_Profiler const &)=delete
void DumpEvents()
Prints all stored events along with their details.
Definition: MHO_Profiler.cc:25
void Lock()
Acquires a lock using fMutex for thread synchronization. TODO we need to eliminate the need for locks...
Definition: MHO_Profiler.hh:115
MHO_Profiler & operator=(MHO_Profiler &&)=delete
void Start()
Definition: Message/src/MHO_Timer.cc:37
Definition: MHO_AdhocFlagging.hh:18
int fLineNumber
Definition: MHO_Profiler.hh:58
double fTime
Definition: MHO_Profiler.hh:60
char fFuncname[PROFILE_INFO_LEN]
Definition: MHO_Profiler.hh:62
MHO_ProfilerFlag
Definition: MHO_Profiler.hh:38
@ pStartFlag
Definition: MHO_Profiler.hh:39
@ pStopFlag
Definition: MHO_Profiler.hh:40
int fFlag
Definition: MHO_Profiler.hh:57
char fFilename[PROFILE_INFO_LEN]
Definition: MHO_Profiler.hh:61
uint64_t fThreadID
Definition: MHO_Profiler.hh:59
Class MHO_ProfileEvent.
Definition: MHO_Profiler.hh:56