Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ProfPerformanceService.cc
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/* ProfPerformanceService.cc (C) 2000-2024 */
9/* */
10/* Performance information using profiling signals. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ValueConvert.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/TraceInfo.h"
19
20#include "arcane/core/FactoryService.h"
21#include "arcane/core/AbstractService.h"
22
23#include "arcane/utils/IProfilingService.h"
24
25#include "arcane/std/ProfilingInfo.h"
26
27// NOTE: Since this file requires libunwind, it is only compiled on
28// UNIX-style OS.
29
30#define UNW_LOCAL_ONLY
31#include <libunwind.h>
32#include <stdio.h>
33#include <cxxabi.h>
34
35#include <sys/time.h>
36#include <signal.h>
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane
42{
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
50class ProfPerformanceService
51: public AbstractService
52, public IProfilingService
53{
54 public:
55
56 explicit ProfPerformanceService(const ServiceBuildInfo& sbi);
57 ~ProfPerformanceService() override;
58
59 public:
60
61 void initialize() override;
62 bool isInitialized() const override { return m_is_initialized; }
63 void startProfiling() override;
64 void switchEvent() override;
65 void stopProfiling() override;
66 void printInfos(bool dump_file) override;
67 void getInfos(Int64Array&) override;
68 void dumpJSON(JSONWriter& writer) override;
69 void reset() override;
70 ITimerMng* timerMng() override { return nullptr; }
71
72 public:
73
74 bool m_is_initialized = false;
75};
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79
80ARCANE_REGISTER_APPLICATION_FACTORY(ProfPerformanceService,
81 IProfilingService,
82 ProfProfilingService);
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86
87ProfPerformanceService::
88ProfPerformanceService(const ServiceBuildInfo& sbi)
89: AbstractService(sbi)
90{
91}
92
93/*---------------------------------------------------------------------------*/
94/*---------------------------------------------------------------------------*/
95
96ProfPerformanceService::
97~ProfPerformanceService()
98{
99}
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
104static void
105_setTimer(Integer usecond)
106{
107 struct itimerval time_val;
108 struct itimerval otime_val;
109 time_val.it_value.tv_sec = 0;
110 time_val.it_value.tv_usec = usecond;
111 time_val.it_interval.tv_sec = 0;
112 time_val.it_interval.tv_usec = 0;
113 int r = setitimer(ITIMER_PROF, &time_val, &otime_val);
114 if (r != 0)
115 cout << "** ERROR in setitimer r=" << r << '\n';
116}
117
118/*---------------------------------------------------------------------------*/
119/*---------------------------------------------------------------------------*/
120
121namespace
122{
123 int nb_total = 0;
124
125 ProfInfos* global_infos = nullptr;
126 bool global_is_active = false;
128 int global_timer_period = 10000;
129} // namespace
130
131extern "C" void
132arcane_prof_handler()
133{
134 static bool is_in_handler = false;
135 // On Linux with gcc, exceptions use libunwind contained
136 // in gcc, and this can cause deadlocks with our usage
137 // if this handler is called during exception unwinding.
138 // To avoid this problem, we do nothing as long as an exception is
139 // active.
141 cout << "** WARNING: ProfHandler in pending exception\n";
142 return;
143 }
144 if (is_in_handler) {
145 cout << "** In handler\n";
146 return;
147 }
148 is_in_handler = true;
149 ++nb_total;
150
151 int overflow_event[MAX_COUNTER];
152 int nb_overflow_event = 1;
153 overflow_event[0] = 0;
154
155 unw_word_t func_ip = 0;
156 unw_word_t offset = 0;
157 {
158 unw_cursor_t cursor;
159 unw_context_t uc;
160 unw_getcontext(&uc);
161 unw_init_local(&cursor, &uc);
162 int current_func = 0;
163 String message;
164
165 // 3 indicates the number of functions before the correct one
166 // (there is this function, then _arcaneProfilingSigFunc
167 // and the signal itself.
168 while (unw_step(&cursor) > 0 && current_func < 3) {
169 //while (current_func<3) {
170 //unw_step(&cursor);
171 unw_get_reg(&cursor, UNW_REG_IP, &func_ip);
172#if 0
173 char func_name_buf[10000];
174 unw_get_proc_name(&cursor,func_name_buf,10000,&offset);
175 cout << "** I=" << current_func << " FUNC NAME=" << func_name_buf
176 << " ip=" << (void*)func_ip << '\n';
177#endif
178 ++current_func;
179 }
180 }
181
182 global_infos->addEvent((void*)(func_ip + offset), overflow_event, nb_overflow_event);
183
184 is_in_handler = false;
185}
186
187/*---------------------------------------------------------------------------*/
188/*---------------------------------------------------------------------------*/
189
190extern "C" void
191_arcaneProfilingSigFunc(int signum)
192{
193 //cout << "**SIGPROF=" << global_is_active << "\n";
194 if (signum != SIGPROF)
195 return;
196 if (global_is_active) {
197 arcane_prof_handler();
198 // It is preferable to position the timer once
199 // the profiling function is called because if the timer is small,
200 // it can trigger in the loop
201 _setTimer(global_timer_period);
202 }
203}
204
205extern "C" void
206_arcaneProfilingSigactionFunc(int val, siginfo_t*, void*)
207{
208 _arcaneProfilingSigFunc(val);
209}
210
211/*---------------------------------------------------------------------------*/
212/*---------------------------------------------------------------------------*/
213
216{
217 if (m_is_initialized)
218 return;
219 m_is_initialized = true;
220
221 if (!global_infos)
222 global_infos = new ProfInfos(traceMng());
223 global_infos->setFunctionDepth(4);
224 global_infos->setNbEventBeforeGettingStack(100);
225}
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
232{
233 global_is_active = true;
234 global_infos->startProfiling();
235
236 struct sigaction sa;
237 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
238 sigemptyset(&sa.sa_mask);
239 sa.sa_sigaction = _arcaneProfilingSigactionFunc;
240 sigaction(SIGPROF, &sa, nullptr);
241
242 _setTimer(global_timer_period);
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248void ProfPerformanceService::
249switchEvent()
250{
251}
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
258{
259 if (!global_infos)
260 return;
261 global_is_active = false;
262 _setTimer(global_timer_period);
263
264 struct sigaction sa;
265 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
266 sigemptyset(&sa.sa_mask);
267 sa.sa_handler = SIG_IGN;
268 sigaction(SIGPROF, &sa, nullptr);
269
270 //info() << "PROFILING: stop profiling nb_total=" << nb_total;
271 global_infos->stopProfiling();
272 //global_infos->printInfos();
273}
274
275/*---------------------------------------------------------------------------*/
276/*---------------------------------------------------------------------------*/
277
279printInfos(bool dump_file)
280{
281 if (global_infos)
282 global_infos->printInfos(dump_file);
283}
284
285/*---------------------------------------------------------------------------*/
286/*---------------------------------------------------------------------------*/
287
289dumpJSON(JSONWriter& writer)
290{
291 if (global_infos)
292 global_infos->dumpJSON(writer);
293}
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
297
298void ProfPerformanceService::
299getInfos(Int64Array&)
300{
301 throw NotImplementedException(A_FUNCINFO);
302}
303
304/*---------------------------------------------------------------------------*/
305/*---------------------------------------------------------------------------*/
306
308reset()
309{
310 if (global_infos)
311 global_infos->reset();
312}
313
314/*---------------------------------------------------------------------------*/
315/*---------------------------------------------------------------------------*/
316
317} // End namespace Arcane
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
#define ARCANE_REGISTER_APPLICATION_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
static bool hasPendingException()
Indicates if there are pending exceptions.
Interface of a profiling service.
Interface of a timer manager.
Definition ITimerMng.h:50
void startProfiling() override
Starts profiling.
void dumpJSON(JSONWriter &writer) override
Writes the profiling information to the writer writer.
void reset() override
Resets the counters.
void initialize() override
Initializes the profiling service.
void stopProfiling() override
Stops profiling.
ITimerMng * timerMng() override
Timer using the features of this service if they exist. Can be null.
bool isInitialized() const override
Indicates if initialize() has already been called.
void printInfos(bool dump_file) override
Displays profiling information.
Structure containing the information to create a service.
ITraceMng * traceMng() const
Trace manager.
-- 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
Int32 Integer
Type representing an integer.