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