Arcane  4.2.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
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/* Informations de performances utilisant les signaux de profiling. */
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/FactoryService.h"
21#include "arcane/AbstractService.h"
22
23#include "arcane/utils/IProfilingService.h"
24
25#include "arcane/std/ProfilingInfo.h"
26
27// NOTE: Ce fichier nécessitant la libunwind, il n'est compilé que sur
28// les OS de style UNIX.
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/*---------------------------------------------------------------------------*/
49class ProfPerformanceService
50: public AbstractService
51, public IProfilingService
52{
53 public:
54
55 explicit ProfPerformanceService(const ServiceBuildInfo& sbi);
56 ~ProfPerformanceService() override;
57
58 public:
59
60 void initialize() override;
61 bool isInitialized() const override { return m_is_initialized; }
62 void startProfiling() override;
63 void switchEvent() override;
64 void stopProfiling() override;
65 bool isRunning() const 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{
123int nb_total = 0;
124
125ProfInfos* global_infos = nullptr;
126bool global_is_active = false;
128int global_timer_period = 10000;
129}
130
131extern "C" void
132arcane_prof_handler()
133{
134 static bool is_in_handler = false;
135 // Sous Linux avec gcc, les exceptions utilisent la libunwind contenue
136 // dans gcc et cela peut provoquer des deadlocks avec notre utilisation
137 // si cet handler est appelé lors du dépilement d'une exception.
138 // Pour éviter ce problème, on ne fait rien tant qu'une exception est
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 // Le 3 indique le nombre de fonctions avant la bonne
166 // (il y a cette fonction, puis le _arcaneProfilingSigFunc
167 // et le signal lui meme.
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 // Il est préférable de positionner le timer une fois
199 // la fonction de profiling appelée car si le timer est petit,
200 // il peut se déclencher dans la boucle
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 if (global_is_active)
234 ARCANE_FATAL("Profiling is already started");
235 global_is_active = true;
236 global_infos->startProfiling();
237
238 struct sigaction sa;
239 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
240 sigemptyset(&sa.sa_mask);
241 sa.sa_sigaction = _arcaneProfilingSigactionFunc;
242 sigaction(SIGPROF, &sa, nullptr);
243
244 _setTimer(global_timer_period);
245}
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250void ProfPerformanceService::
251switchEvent()
252{
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
260{
261 if (!global_infos)
262 return;
263
264 global_is_active = false;
265 _setTimer(global_timer_period);
266
267 struct sigaction sa;
268 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
269 sigemptyset(&sa.sa_mask);
270 sa.sa_handler = SIG_IGN;
271 sigaction(SIGPROF, &sa, nullptr);
272
273 //info() << "PROFILING: stop profiling nb_total=" << nb_total;
274 global_infos->stopProfiling();
275 //global_infos->printInfos();
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
282printInfos(bool dump_file)
283{
284 if (global_infos)
285 global_infos->printInfos(dump_file);
286}
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
292dumpJSON(JSONWriter& writer)
293{
294 if (global_infos)
295 global_infos->dumpJSON(writer);
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301void ProfPerformanceService::
302getInfos(Int64Array&)
303{
304 throw NotImplementedException(A_FUNCINFO);
305}
306
307
308/*---------------------------------------------------------------------------*/
309/*---------------------------------------------------------------------------*/
310
312reset()
313{
314 if (global_infos)
315 global_infos->reset();
316}
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
322isRunning() const
323{
324 return global_is_active;
325}
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329
330} // End namespace Arcane
331
332/*---------------------------------------------------------------------------*/
333/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCANE_REGISTER_APPLICATION_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
static bool hasPendingException()
Indique si des exceptions sont en cours.
Interface d'un service de profiling.
Interface d'un gestionnaire de timer.
Definition ITimerMng.h:49
Exception lorsqu'une fonction n'est pas implémentée.
void startProfiling() override
Démarre un profiling.
void dumpJSON(JSONWriter &writer) override
Ecrit les infos de profiling dans l'écrivain writer.
void reset() override
Remet à zéro les compteurs.
bool isRunning() const override
Indique si le profiling est en cours.
void initialize() override
Initialise le service de profiling.
void stopProfiling() override
Stoppe le profiling.
ITimerMng * timerMng() override
Timer utilisant les fonctionnalités de ce service si elles existent. Peut être nul.
bool isInitialized() const override
Indique si initialize() a déjà été appelé
void printInfos(bool dump_file) override
Affiche les infos de profiling.
Structure contenant les informations pour créer un service.
Chaîne de caractères unicode.
ITraceMng * traceMng() const
Gestionnaire de trace.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:119
Int32 Integer
Type représentant un entier.