1 #ifndef NETGEN_CORE_PAJE_TRACE_HPP 2 #define NETGEN_CORE_PAJE_TRACE_HPP 3 4 #include <limits> 5 #include <vector> 6 7 #include "logging.hpp" // for logger 8 #include "ngcore_api.hpp" // for NGCORE_API 9 #include "utils.hpp" 10 11 namespace ngcore 12 { 13 14 extern NGCORE_API class PajeTrace *trace; 15 class PajeTrace 16 { 17 public: 18 using TClock = std::chrono::system_clock; 19 20 protected: 21 std::shared_ptr<Logger> logger = GetLogger("PajeTrace"); 22 private: 23 NGCORE_API static size_t max_tracefile_size; 24 NGCORE_API static bool trace_thread_counter; 25 NGCORE_API static bool trace_threads; 26 NGCORE_API static bool mem_tracing_enabled; 27 28 bool tracing_enabled; 29 TTimePoint start_time; 30 int nthreads; 31 size_t n_memory_events_at_start; 32 33 public: 34 NGCORE_API void WriteTimingChart(); 35 #ifdef NETGEN_TRACE_MEMORY 36 NGCORE_API void WriteMemoryChart( std::string fname ); 37 #endif // NETGEN_TRACE_MEMORY 38 39 // Approximate number of events to trace. Tracing will 40 // be stopped if any thread reaches this number of events 41 unsigned int max_num_events_per_thread; 42 SetTraceMemory(bool trace_memory)43 static void SetTraceMemory( bool trace_memory ) 44 { 45 mem_tracing_enabled = trace_memory; 46 } 47 SetTraceThreads(bool atrace_threads)48 static void SetTraceThreads( bool atrace_threads ) 49 { 50 trace_threads = atrace_threads; 51 } 52 SetTraceThreadCounter(bool trace_threads)53 static void SetTraceThreadCounter( bool trace_threads ) 54 { 55 trace_thread_counter = trace_threads; 56 } 57 SetMaxTracefileSize(size_t max_size)58 static void SetMaxTracefileSize( size_t max_size ) 59 { 60 max_tracefile_size = max_size; 61 } 62 63 std::string tracefile_name; 64 65 struct Job 66 { 67 int job_id; 68 const std::type_info *type; 69 TTimePoint start_time; 70 TTimePoint stop_time; 71 }; 72 73 struct Task 74 { 75 int thread_id; 76 77 int id; 78 int id_type; 79 80 int additional_value; 81 82 TTimePoint time; 83 bool is_start; 84 85 static constexpr int ID_NONE = -1; 86 static constexpr int ID_JOB = 1; 87 static constexpr int ID_TIMER = 2; 88 }; 89 90 struct TimerEvent 91 { 92 int timer_id; 93 TTimePoint time; 94 bool is_start; 95 int thread_id; 96 operator <ngcore::PajeTrace::TimerEvent97 bool operator < (const TimerEvent & other) const { return time < other.time; } 98 }; 99 100 struct ThreadLink 101 { 102 int thread_id; 103 int key; 104 TTimePoint time; 105 bool is_start; operator <ngcore::PajeTrace::ThreadLink106 bool operator < (const ThreadLink & other) const { return time < other.time; } 107 }; 108 109 struct MemoryEvent 110 { 111 TTimePoint time; 112 size_t size; 113 int id; 114 bool is_alloc; 115 operator <ngcore::PajeTrace::MemoryEvent116 bool operator < (const MemoryEvent & other) const { return time < other.time; } 117 }; 118 119 std::vector<std::vector<Task> > tasks; 120 std::vector<Job> jobs; 121 std::vector<TimerEvent> timer_events; 122 std::vector<std::vector<ThreadLink> > links; 123 NGCORE_API static std::vector<MemoryEvent> memory_events; 124 125 public: 126 NGCORE_API void StopTracing(); 127 128 PajeTrace() = delete; 129 PajeTrace(const PajeTrace &) = delete; 130 PajeTrace(PajeTrace &&) = delete; 131 NGCORE_API PajeTrace(int anthreads, std::string aname = ""); 132 NGCORE_API ~PajeTrace(); 133 134 void operator=(const PajeTrace &) = delete; 135 void operator=(PajeTrace &&) = delete; 136 StartTimer(int timer_id)137 void StartTimer(int timer_id) 138 { 139 if(!tracing_enabled) return; 140 if(unlikely(timer_events.size() == max_num_events_per_thread)) 141 StopTracing(); 142 timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true}); 143 } 144 StopTimer(int timer_id)145 void StopTimer(int timer_id) 146 { 147 if(!tracing_enabled) return; 148 if(unlikely(timer_events.size() == max_num_events_per_thread)) 149 StopTracing(); 150 timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), false}); 151 } 152 AllocMemory(int id,size_t size)153 void AllocMemory(int id, size_t size) 154 { 155 if(!mem_tracing_enabled) return; 156 memory_events.push_back(MemoryEvent{GetTimeCounter(), size, id, true}); 157 } 158 FreeMemory(int id,size_t size)159 void FreeMemory(int id, size_t size) 160 { 161 if(!mem_tracing_enabled) return; 162 memory_events.push_back(MemoryEvent{GetTimeCounter(), size, id, false}); 163 } 164 ChangeMemory(int id,long long size)165 void ChangeMemory(int id, long long size) 166 { 167 if(size>0) 168 AllocMemory(id, size); 169 if(size<0) 170 FreeMemory(id, -size); 171 } 172 173 StartTask(int thread_id,int id,int id_type=Task::ID_NONE,int additional_value=-1)174 NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1) 175 { 176 if(!tracing_enabled) return -1; 177 if(!trace_threads && !trace_thread_counter) return -1; 178 if(unlikely(tasks[thread_id].size() == max_num_events_per_thread)) 179 StopTracing(); 180 int task_num = tasks[thread_id].size(); 181 tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter(), true} ); 182 return task_num; 183 } 184 StopTask(int thread_id,int id,int id_type=Task::ID_NONE)185 void StopTask(int thread_id, int id, int id_type = Task::ID_NONE) 186 { 187 if(!trace_threads && !trace_thread_counter) return; 188 tasks[thread_id].push_back( Task{thread_id, id, id_type, 0, GetTimeCounter(), false} ); 189 } 190 StartJob(int job_id,const std::type_info & type)191 void StartJob(int job_id, const std::type_info & type) 192 { 193 if(!tracing_enabled) return; 194 if(jobs.size() == max_num_events_per_thread) 195 StopTracing(); 196 jobs.push_back( Job{job_id, &type, GetTimeCounter()} ); 197 } 198 StopJob()199 void StopJob() 200 { 201 if(tracing_enabled) 202 jobs.back().stop_time = GetTimeCounter(); 203 } 204 StartLink(int thread_id,int key)205 void StartLink(int thread_id, int key) 206 { 207 if(!tracing_enabled) return; 208 if(links[thread_id].size() == max_num_events_per_thread) 209 StopTracing(); 210 links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} ); 211 } 212 StopLink(int thread_id,int key)213 void StopLink(int thread_id, int key) 214 { 215 if(!tracing_enabled) return; 216 if(links[thread_id].size() == max_num_events_per_thread) 217 StopTracing(); 218 links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} ); 219 } 220 221 void Write( const std::string & filename ); 222 223 void SendData(); // MPI parallel data reduction 224 225 }; 226 } // namespace ngcore 227 228 #endif // NETGEN_CORE_PAJE_TRACE_HPP 229