Arcane  v3.14.10.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-2023 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-2023 */
9/* */
10/* Informations de performances utilisant les signaux de profiling. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/ValueConvert.h"
17#include "arcane/utils/NotImplementedException.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/FatalErrorException.h"
20#include "arcane/utils/TraceInfo.h"
21
22#include "arcane/FactoryService.h"
23#include "arcane/AbstractService.h"
24
25#include "arcane/utils/IProfilingService.h"
26
27#include "arcane/std/ProfilingInfo.h"
28
29// NOTE: Ce fichier nécessitant la libunwind, il n'est compilé que sur
30// les OS de style UNIX.
31
32#define UNW_LOCAL_ONLY
33#include <libunwind.h>
34#include <stdio.h>
35#include <cxxabi.h>
36
37#include <sys/time.h>
38#include <signal.h>
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43namespace Arcane
44{
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
52: public AbstractService
53, public IProfilingService
54{
55 public:
56
58 ~ProfPerformanceService() override;
59
60 public:
61
62 void initialize() override;
63 bool isInitialized() const override { return m_is_initialized; }
64 void startProfiling() override;
65 void switchEvent() override;
66 void stopProfiling() override;
67 void printInfos(bool dump_file) override;
68 void getInfos(Int64Array&) override;
69 void dumpJSON(JSONWriter& writer) override;
70 void reset() override;
71 ITimerMng* timerMng() override { return nullptr; }
72
73 public:
74
75 bool m_is_initialized = false;
76};
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
81ARCANE_REGISTER_APPLICATION_FACTORY(ProfPerformanceService,
82 IProfilingService,
83 ProfProfilingService);
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88ProfPerformanceService::
89ProfPerformanceService(const ServiceBuildInfo& sbi)
90: AbstractService(sbi)
91{
92}
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
97ProfPerformanceService::
98~ProfPerformanceService()
99{
100}
101
102/*---------------------------------------------------------------------------*/
103/*---------------------------------------------------------------------------*/
104
105static void
106_setTimer(Integer usecond)
107{
108 struct itimerval time_val;
109 struct itimerval otime_val;
110 time_val.it_value.tv_sec = 0;
111 time_val.it_value.tv_usec = usecond;
112 time_val.it_interval.tv_sec = 0;
113 time_val.it_interval.tv_usec = 0;
114 int r = setitimer(ITIMER_PROF,&time_val,&otime_val);
115 if (r!=0)
116 cout << "** ERROR in setitimer r=" << r << '\n';
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122namespace
123{
124int nb_total = 0;
125
126ProfInfos* global_infos = nullptr;
127bool global_is_active = false;
129int global_timer_period = 10000;
130}
131
132extern "C" void
133arcane_prof_handler()
134{
135 static bool is_in_handler = false;
136 // Sous Linux avec gcc, les exceptions utilisent la libunwind contenue
137 // dans gcc et cela peut provoquer des deadlocks avec notre utilisation
138 // si cet handler est appelé lors du dépilement d'une exception.
139 // Pour éviter ce problème, on ne fait rien tant qu'une exception est
140 // active.
142 cout << "** WARNING: ProfHandler in pending exception\n";
143 return;
144 }
145 if (is_in_handler){
146 cout << "** In handler\n";
147 return;
148 }
149 is_in_handler = true;
150 ++nb_total;
151
152 int overflow_event[MAX_COUNTER];
153 int nb_overflow_event = 1;
154 overflow_event[0] = 0;
155
156 unw_word_t func_ip = 0;
157 unw_word_t offset = 0;
158 {
159 unw_cursor_t cursor;
160 unw_context_t uc;
161 unw_getcontext(&uc);
162 unw_init_local(&cursor, &uc);
163 int current_func = 0;
164 String message;
165
166 // Le 3 indique le nombre de fonctions avant la bonne
167 // (il y a cette fonction, puis le _arcaneProfilingSigFunc
168 // et le signal lui meme.
169 while (unw_step(&cursor) > 0 && current_func<3) {
170 //while (current_func<3) {
171 //unw_step(&cursor);
172 unw_get_reg(&cursor, UNW_REG_IP, &func_ip);
173#if 0
174 char func_name_buf[10000];
175 unw_get_proc_name(&cursor,func_name_buf,10000,&offset);
176 cout << "** I=" << current_func << " FUNC NAME=" << func_name_buf
177 << " ip=" << (void*)func_ip << '\n';
178#endif
179 ++current_func;
180 }
181 }
182
183 global_infos->addEvent((void*)(func_ip+offset),overflow_event,nb_overflow_event);
184
185 is_in_handler = false;
186}
187
188/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
190
191extern "C" void
192_arcaneProfilingSigFunc(int signum)
193{
194 //cout << "**SIGPROF=" << global_is_active << "\n";
195 if (signum!=SIGPROF)
196 return;
197 if (global_is_active){
198 arcane_prof_handler();
199 // Il est préférable de positionner le timer une fois
200 // la fonction de profiling appelée car si le timer est petit,
201 // il peut se déclencher dans la boucle
202 _setTimer(global_timer_period);
203 }
204}
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
211{
212 if (m_is_initialized)
213 return;
214 m_is_initialized = true;
215
216 if (!global_infos)
218 global_infos->setFunctionDepth(4);
219 global_infos->setNbEventBeforeGettingStack(100);
220}
221
222/*---------------------------------------------------------------------------*/
223/*---------------------------------------------------------------------------*/
224
227{
228 global_is_active = true;
229 global_infos->startProfiling();
230 ::sigset(SIGPROF,_arcaneProfilingSigFunc);
231 _setTimer(global_timer_period);
232}
233
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
237void ProfPerformanceService::
238switchEvent()
239{
240}
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
244
247{
248 if (!global_infos)
249 return;
250 global_is_active = false;
251 _setTimer(global_timer_period);
252 ::sigset(SIGPROF,SIG_IGN);
253 //info() << "PROFILING: stop profiling nb_total=" << nb_total;
254 global_infos->stopProfiling();
255 //global_infos->printInfos();
256}
257
258/*---------------------------------------------------------------------------*/
259/*---------------------------------------------------------------------------*/
260
263{
264 if (global_infos)
265 global_infos->printInfos(dump_file);
266}
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281void ProfPerformanceService::
282getInfos(Int64Array&)
283{
284 throw NotImplementedException(A_FUNCINFO);
285}
286
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
292reset()
293{
294 if (global_infos)
295 global_infos->reset();
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301} // End namespace Arcane
302
303/*---------------------------------------------------------------------------*/
304/*---------------------------------------------------------------------------*/
#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:120
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 -*-