Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ProfilingInfo.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* ProfilingInfo.h (C) 2000-2024 */
9/* */
10/* Structures for profiling information. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_STD_PROFILINGINFO_H
13#define ARCANE_STD_PROFILINGINFO_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/TraceAccessor.h"
18#include "arcane/utils/FatalErrorException.h"
19
20#include <map>
21#include <set>
22
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26namespace Arcane
27{
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32static const int MAX_COUNTER = 3;
33static const int MAX_STACK = 25;
34static const int MAX_FUNC = 10000;
35static const int MAX_FUNC_LEN = 500;
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40class ProfFuncInfo
41{
42 public:
43
44 ProfFuncInfo()
45 : m_index(0)
46 , m_do_stack(false)
47 , m_has_func_name(false)
48 {
49 m_func_name[0] = '\0';
50 for (Integer i = 0; i < MAX_COUNTER; ++i)
51 m_counters[i] = 0;
52 }
53
54 public:
55
56 Int32 index() const { return m_index; }
57 void setIndex(Int32 v) { m_index = v; }
58 bool hasFuncName() const { return m_has_func_name; }
59 void setHasFuncName(bool v) { m_has_func_name = v; }
60
61 private:
62
63 Int32 m_index;
64
65 public:
66
67 bool m_do_stack;
68
69 private:
70
71 bool m_has_func_name;
72
73 public:
74
75 Int64 m_counters[MAX_COUNTER];
76 // TODO: Do not use a max size but use a buffer containing
77 // all names
78 char m_func_name[MAX_FUNC_LEN + 10];
79};
80
81/*---------------------------------------------------------------------------*/
82/*---------------------------------------------------------------------------*/
83
84class ProfStackInfo
85{
86 public:
87
88 ProfStackInfo()
89 {
90 for (Integer i = 0; i < MAX_STACK; ++i)
91 m_funcs_info_indexes[i] = (-1);
92 }
93
94 public:
95
96 bool operator<(const ProfStackInfo& pfi) const
97 {
98 return ::memcmp(m_funcs_info_indexes, pfi.m_funcs_info_indexes, MAX_STACK * sizeof(Int32)) < 0;
99 }
100
101 public:
102
103 Int32 m_funcs_info_indexes[MAX_STACK];
104};
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109class ProfAddrInfo
110{
111 public:
112 public:
113
114 ProfAddrInfo()
115 : m_func_info(0)
116 {
117 for (Integer i = 0; i < MAX_COUNTER; ++i)
118 m_counters[i] = 0;
119 }
120
121 public:
122
123 Int64 m_counters[MAX_COUNTER];
124 ProfFuncInfo* m_func_info;
125};
126
127/*---------------------------------------------------------------------------*/
128/*---------------------------------------------------------------------------*/
129
131{
132 public:
133
134 typedef ProfFuncInfo* ProfFuncInfoPtr;
135
136 public:
137
138 bool operator()(const ProfFuncInfoPtr& lhs, const ProfFuncInfoPtr& rhs) const
139 {
140 return (lhs->m_counters[0] > rhs->m_counters[0]);
141 }
142};
143
144static const int MAX_STATIC_ALLOC = 100000;
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
148
159template <typename _Tp>
160class StaticAlloc
161{
162 public:
163
164 typedef size_t size_type;
165 typedef ptrdiff_t difference_type;
166 typedef _Tp* pointer;
167 typedef const _Tp* const_pointer;
168 typedef _Tp& reference;
169 typedef const _Tp& const_reference;
170 typedef _Tp value_type;
171
172 template <typename _Tp1>
173 struct rebind
174 {
175 typedef StaticAlloc<_Tp1> other;
176 };
177
178 StaticAlloc() ARCANE_NOEXCEPT
179 {
180 }
181
182 StaticAlloc(const StaticAlloc&) ARCANE_NOEXCEPT
183 {
184 }
185
186 template <typename _Tp1>
187 StaticAlloc(const StaticAlloc<_Tp1>&) ARCANE_NOEXCEPT {}
188
189 ~StaticAlloc() ARCANE_NOEXCEPT {}
190
191 void construct(pointer __p, const _Tp& __val)
192 {
193 ::new ((void*)__p) _Tp(__val);
194 }
195
196 void destroy(pointer __p) { __p->~_Tp(); }
197
198 pointer allocate(size_type /*__n*/, const void* = 0)
199 {
200 //return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
201 pointer p = &m_buf[m_buf_index];
202 //TODO: make atomic + check overflow
203 ++m_buf_index;
204 if (m_buf_index >= (int)(0.9 * MAX_STATIC_ALLOC))
205 cout << "** WARNING: allocate near max memory\n";
206 if (m_buf_index >= MAX_STATIC_ALLOC)
207 throw FatalErrorException("StaticAlloc", "max static alloc reached");
208 return p;
209 }
210 void deallocate(pointer, size_type)
211 {
212 // Deallocations are not used because we must not delete
213 // elements from the map
214 //::operator delete(__p);
215 }
216
217 private:
218
219 static _Tp m_buf[MAX_STATIC_ALLOC];
220 static int m_buf_index;
221};
222
223template <typename _Tp> int
224StaticAlloc<_Tp>::m_buf_index = 0;
225
226template <typename _Tp> _Tp
227StaticAlloc<_Tp>::m_buf[MAX_STATIC_ALLOC];
228
230
231class ProfInfos
232: public TraceAccessor
233{
234 class SortedProfStackInfo
235 {
236 public:
237
238 SortedProfStackInfo(const ProfStackInfo& psi, Int64 nb_count)
239 : m_stack_info(psi)
240 , m_nb_count(nb_count)
241 {
242 }
243
244 public:
245
246 bool operator<(const SortedProfStackInfo& pfi) const
247 {
248 return this->m_nb_count > pfi.m_nb_count;
249 }
250 const ProfStackInfo& stackInfo() const { return m_stack_info; }
251 Int64 nbCount() const { return m_nb_count; }
252
253 private:
254
255 ProfStackInfo m_stack_info;
256 Int64 m_nb_count;
257 };
258
259 private:
260
261 class IStackInfoProvider;
262 class IFuncInfoProvider;
264 class LibUnwindFuncInfos;
265 class LibUnwindStackInfo;
266 class BacktraceFuncInfos;
267 class BacktraceStackInfo;
268
269 private:
270
271 struct FuncAddrInfo
272 {
273 FuncAddrInfo()
274 : start_addr(0)
275 , func_name(0)
276 {}
277 void* start_addr;
278 const char* func_name;
279 };
280
281 public:
282
283 ProfInfos(ITraceMng* tm);
284 ~ProfInfos();
285
286 public:
287
288 // IMPORTANT:
289 // std::map must not use dynamic allocation
290 // because they are used in the addEvent() method which can be
291 // called at any time and thus in a malloc/realloc/free
292 // and this can therefore cause a deadlock with threads.
293#if defined(ARCCORE_OS_WIN32) || defined(ARCCORE_OS_MACOS)
294 typedef std::map<void*, ProfAddrInfo> AddrMap;
295 typedef std::map<Int64, ProfFuncInfo*> FuncMap;
296 typedef std::map<ProfStackInfo, Int64> StackMap;
297#else
298 typedef std::map<void*, ProfAddrInfo, std::less<void*>, StaticAlloc<std::pair<void* const, ProfAddrInfo>>> AddrMap;
299 typedef std::map<Int64, ProfFuncInfo*, std::less<Int64>, StaticAlloc<std::pair<const Int64, ProfFuncInfo*>>> FuncMap;
300 typedef std::map<ProfStackInfo, Int64, std::less<ProfStackInfo>, StaticAlloc<std::pair<const ProfStackInfo, Int64>>> StackMap;
301#endif
302
303 public:
304
305 void printInfos(bool dump_file);
306 void dumpJSON(JSONWriter& writer);
307 void getInfos(Int64Array&);
308 void startProfiling();
309 void addEvent(void* address, int overflow_event[MAX_COUNTER], int nb_overflow_event);
310 void stopProfiling();
311 void reset();
312
313 public:
314
315 void setFunctionDepth(int v);
316 void setPeriod(int v);
317 void setNbEventBeforeGettingStack(Integer v) { m_nb_event_before_getting_stack = v; }
318 Int64 nbEventBeforeGettingStack() const { return m_nb_event_before_getting_stack; }
319
320 private:
321
322 AddrMap m_addr_map;
323 FuncMap m_func_map;
324 StackMap m_stack_map;
325 Int64 m_total_event = 0;
326 Int64 m_total_stack = 0;
327 Int64 m_counters[MAX_COUNTER];
328 Int32 m_current_func_info = 0;
329 ProfFuncInfo m_func_info_buffer[MAX_FUNC];
330 int m_period = 0;
331 Int64 m_nb_event_before_getting_stack = 5000;
332 int m_function_depth = 3;
333 bool m_use_backtrace = false;
334 bool m_use_libunwind = false;
335 MonoFuncAddrGetter* m_mono_func_getter = nullptr;
336 bool m_is_started = false;
337 IFuncInfoProvider* m_default_func_info_provider = nullptr;
338 IFuncInfoProvider* m_libunwind_func_info_provider = nullptr;
339 IFuncInfoProvider* m_backtrace_func_info_provider = nullptr;
340 IFuncInfoProvider* m_func_info_provider = nullptr;
341
342 protected:
343
344 void _addEvent(void* address, int overflow_event[MAX_COUNTER], int nb_overflow_event,
345 IStackInfoProvider& stack_info, Integer function_depth);
346 bool _getFunc(void* addr, FuncAddrInfo& info);
347 void _sortFunctions(std::set<ProfFuncInfo*, ProfFuncComparer>& sorted_func);
348
349 private:
350
351 ProfFuncInfo* _getNextFuncInfo();
352 ProfFuncInfo& _funcInfoFromIndex(Int32 index) { return m_func_info_buffer[index]; }
353 void _storeAddress(void* address, bool is_counter0, int overflow_event[MAX_COUNTER], int nb_overflow_event,
354 bool* do_add, bool* do_stack, bool* func_already_added);
355 void _checkNotStarted();
356};
357
358/*---------------------------------------------------------------------------*/
359/*---------------------------------------------------------------------------*/
360
361} // End namespace Arcane
362
363/*---------------------------------------------------------------------------*/
364/*---------------------------------------------------------------------------*/
365
366#endif
Interface to retrieve call stack information.
Static allocator for profiling.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Array< Int64 > Int64Array
Dynamic one-dimensional array of 64-bit integers.
Definition UtilsTypes.h:125
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
std::int32_t Int32
Signed integer type of 32 bits.