Arcane  v3.15.0.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-2024 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/*---------------------------------------------------------------------------*/
50: public AbstractService
51, public IProfilingService
52{
53 public:
54
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 void printInfos(bool dump_file) override;
66 void getInfos(Int64Array&) override;
67 void dumpJSON(JSONWriter& writer) override;
68 void reset() override;
69 ITimerMng* timerMng() override { return nullptr; }
70
71 public:
72
73 bool m_is_initialized = false;
74};
75
76/*---------------------------------------------------------------------------*/
77/*---------------------------------------------------------------------------*/
78
79ARCANE_REGISTER_APPLICATION_FACTORY(ProfPerformanceService,
80 IProfilingService,
81 ProfProfilingService);
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
86ProfPerformanceService::
87ProfPerformanceService(const ServiceBuildInfo& sbi)
88: AbstractService(sbi)
89{
90}
91
92/*---------------------------------------------------------------------------*/
93/*---------------------------------------------------------------------------*/
94
95ProfPerformanceService::
96~ProfPerformanceService()
97{
98}
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103static void
104_setTimer(Integer usecond)
105{
106 struct itimerval time_val;
107 struct itimerval otime_val;
108 time_val.it_value.tv_sec = 0;
109 time_val.it_value.tv_usec = usecond;
110 time_val.it_interval.tv_sec = 0;
111 time_val.it_interval.tv_usec = 0;
112 int r = setitimer(ITIMER_PROF,&time_val,&otime_val);
113 if (r!=0)
114 cout << "** ERROR in setitimer r=" << r << '\n';
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
120namespace
121{
122int nb_total = 0;
123
124ProfInfos* global_infos = nullptr;
125bool global_is_active = false;
127int global_timer_period = 10000;
128}
129
130extern "C" void
131arcane_prof_handler()
132{
133 static bool is_in_handler = false;
134 // Sous Linux avec gcc, les exceptions utilisent la libunwind contenue
135 // dans gcc et cela peut provoquer des deadlocks avec notre utilisation
136 // si cet handler est appelé lors du dépilement d'une exception.
137 // Pour éviter ce problème, on ne fait rien tant qu'une exception est
138 // active.
140 cout << "** WARNING: ProfHandler in pending exception\n";
141 return;
142 }
143 if (is_in_handler){
144 cout << "** In handler\n";
145 return;
146 }
147 is_in_handler = true;
148 ++nb_total;
149
150 int overflow_event[MAX_COUNTER];
151 int nb_overflow_event = 1;
152 overflow_event[0] = 0;
153
154 unw_word_t func_ip = 0;
155 unw_word_t offset = 0;
156 {
157 unw_cursor_t cursor;
158 unw_context_t uc;
159 unw_getcontext(&uc);
160 unw_init_local(&cursor, &uc);
161 int current_func = 0;
162 String message;
163
164 // Le 3 indique le nombre de fonctions avant la bonne
165 // (il y a cette fonction, puis le _arcaneProfilingSigFunc
166 // et le signal lui meme.
167 while (unw_step(&cursor) > 0 && current_func<3) {
168 //while (current_func<3) {
169 //unw_step(&cursor);
170 unw_get_reg(&cursor, UNW_REG_IP, &func_ip);
171#if 0
172 char func_name_buf[10000];
173 unw_get_proc_name(&cursor,func_name_buf,10000,&offset);
174 cout << "** I=" << current_func << " FUNC NAME=" << func_name_buf
175 << " ip=" << (void*)func_ip << '\n';
176#endif
177 ++current_func;
178 }
179 }
180
181 global_infos->addEvent((void*)(func_ip+offset),overflow_event,nb_overflow_event);
182
183 is_in_handler = false;
184}
185
186/*---------------------------------------------------------------------------*/
187/*---------------------------------------------------------------------------*/
188
189extern "C" void
190_arcaneProfilingSigFunc(int signum)
191{
192 //cout << "**SIGPROF=" << global_is_active << "\n";
193 if (signum!=SIGPROF)
194 return;
195 if (global_is_active){
196 arcane_prof_handler();
197 // Il est préférable de positionner le timer une fois
198 // la fonction de profiling appelée car si le timer est petit,
199 // il peut se déclencher dans la boucle
200 _setTimer(global_timer_period);
201 }
202}
203
204extern "C" void
205_arcaneProfilingSigactionFunc(int val, siginfo_t*,void*)
206{
207 _arcaneProfilingSigFunc(val);
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
215{
216 if (m_is_initialized)
217 return;
218 m_is_initialized = true;
219
220 if (!global_infos)
222 global_infos->setFunctionDepth(4);
223 global_infos->setNbEventBeforeGettingStack(100);
224}
225
226/*---------------------------------------------------------------------------*/
227/*---------------------------------------------------------------------------*/
228
231{
232 global_is_active = true;
233 global_infos->startProfiling();
234
235 struct sigaction sa;
236 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
237 sigemptyset(&sa.sa_mask);
238 sa.sa_sigaction = _arcaneProfilingSigactionFunc;
239 sigaction(SIGPROF, &sa, nullptr);
240
241 _setTimer(global_timer_period);
242}
243
244/*---------------------------------------------------------------------------*/
245/*---------------------------------------------------------------------------*/
246
247void ProfPerformanceService::
248switchEvent()
249{
250}
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
257{
258 if (!global_infos)
259 return;
260 global_is_active = false;
261 _setTimer(global_timer_period);
262
263 struct sigaction sa;
264 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
265 sigemptyset(&sa.sa_mask);
266 sa.sa_handler = SIG_IGN;
267 sigaction(SIGPROF, &sa, nullptr);
268
269 //info() << "PROFILING: stop profiling nb_total=" << nb_total;
270 global_infos->stopProfiling();
271 //global_infos->printInfos();
272}
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
279{
280 if (global_infos)
281 global_infos->printInfos(dump_file);
282}
283
284/*---------------------------------------------------------------------------*/
285/*---------------------------------------------------------------------------*/
286
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
296
297void ProfPerformanceService::
298getInfos(Int64Array&)
299{
300 throw NotImplementedException(A_FUNCINFO);
301}
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)
Enregistre un service de fabrique pour la classe aclass.
Classe de base d'un service.
Tableau d'items de types quelconques.
Interface d'un service de profiling.
Interface d'un gestionnaire de timer.
Definition ITimerMng.h:53
Ecrivain au format JSON.
Definition JSONWriter.h:33
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Service de profiling utilisant 'setitimer'.
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.
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.
static bool hasPendingException()
Indique si des exceptions sont en cours.
Exception lorsqu'une fonction n'est pas implémentée.
ITraceMng * traceMng() const
Gestionnaire de trace.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-