16#include "arcane/utils/Array.h"
17#include "arcane/utils/String.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/JSONWriter.h"
22#include "arcane/std/ProfilingInfo.h"
28#include "arcane_packages.h"
32#ifdef ARCANE_HAS_PACKAGE_LIBUNWIND
41#if defined(ARCANE_OS_LINUX)
50#if defined(ARCANE_OS_LINUX)
51#define ARCANE_HAS_GLIBC_BACKTRACE
54#ifdef ARCANE_USE_MALLOC_HOOK
80 virtual Integer nbIndex()
const = 0;
81 virtual intptr_t functionStartAddress(
Int32 stack_index) = 0;
82 virtual void fillStack(
Integer function_depth) = 0;
83 virtual void setFunc(
Int32 func_index,
Int32 stack_index) = 0;
108 pfi.m_func_name[0] =
'\0';
109 pfi.setHasFuncName(
true);
116#ifdef ARCANE_HAS_PACKAGE_LIBUNWIND
117class ProfInfos::LibUnwindFuncInfos
124 Int32 func_index = pfi.index();
125 unw_cursor_t* cursor = &func_cursor[func_index];
127 unw_get_proc_name(cursor, pfi.m_func_name, MAX_FUNC_LEN, &offset);
128 pfi.setHasFuncName(
true);
130 void setFunc(
Int32 func_index,
const unw_cursor_t& cursor)
132 func_cursor[func_index] = cursor;
137 unw_cursor_t func_cursor[MAX_FUNC];
140class ProfInfos::LibUnwindStackInfo
141:
public IStackInfoProvider
145 LibUnwindStackInfo(LibUnwindFuncInfos* func_infos)
147 , m_func_infos(func_infos)
152 void fillStack(Integer function_depth)
override
158 unw_init_local(&cursor, &uc);
159 unw_proc_info_t proc_info;
160 while (unw_step(&cursor) > 0 && index < (MAX_STACK + function_depth)) {
161 unw_get_proc_info(&cursor, &proc_info);
162 m_cursors[index] = cursor;
163 m_proc_start[index] = proc_info.start_ip;
168 void setFunc(Int32 func_index, Int32 stack_index)
override
170 m_func_infos->setFunc(func_index, m_cursors[stack_index]);
175 Integer nbIndex()
const override {
return m_nb_index; }
176 intptr_t functionStartAddress(Int32 stack_index)
override
178 return (intptr_t)m_proc_start[stack_index];
184 unw_cursor_t m_cursors[256];
185 unw_word_t m_proc_start[256];
187 LibUnwindFuncInfos* m_func_infos;
194#ifdef ARCANE_HAS_GLIBC_BACKTRACE
195class ProfInfos::BacktraceFuncInfos
196:
public IFuncInfoProvider
200 void fillFuncName(ProfFuncInfo& pfi)
override
202 Int32 func_index = pfi.index();
204 const char* func_name = func_dl_info[func_index].dli_sname;
206 for (; copy_index < MAX_FUNC_LEN; ++copy_index) {
207 char c = func_name[copy_index];
208 pfi.m_func_name[copy_index] = c;
213 pfi.m_func_name[copy_index] =
'\0';
214 pfi.setHasFuncName(
true);
216 void setFunc(Int32 func_index,
const Dl_info& dl_info)
218 func_dl_info[func_index] = dl_info;
223 Dl_info func_dl_info[MAX_FUNC];
225class ProfInfos::BacktraceStackInfo
226:
public IStackInfoProvider
230 BacktraceStackInfo(BacktraceFuncInfos* func_infos)
232 , m_func_infos(func_infos)
237 void fillStack(Integer function_depth)
override
239 ARCANE_UNUSED(function_depth);
241 m_nb_index = backtrace(addrs, 64);
242 for (Integer index = 0; index < m_nb_index; ++index) {
243 int err_code = dladdr(addrs[index], &m_dl_infos[index]);
245 m_proc_start[index] = (intptr_t)m_dl_infos[index].dli_saddr;
247 m_proc_start[index] = 0;
250 void setFunc(Int32 func_index, Int32 stack_index)
override
252 m_func_infos->setFunc(func_index, m_dl_infos[stack_index]);
257 Integer nbIndex()
const override {
return m_nb_index; }
258 intptr_t functionStartAddress(Int32 stack_index)
override
260 return (intptr_t)m_proc_start[stack_index];
266 std::array<Dl_info, 256> m_dl_infos = {};
267 std::array<intptr_t, 256> m_proc_start = {};
269 BacktraceFuncInfos* m_func_infos;
276class MonoFuncAddrGetter
284 typedef void* (*mono_jit_info_get_code_start_func)(_MonoJitInfo* ji);
285 typedef _MonoDomain* (*mono_domain_get_func)();
286 typedef _MonoJitInfo* (*mono_jit_info_table_find_func)(_MonoDomain*,
void* ip);
287 typedef char* (*mono_pmip_func)(
void* ip);
288 typedef _MonoMethod* (*mono_jit_info_get_method_func)(_MonoJitInfo* ji);
289 typedef char* (*mono_method_full_name_func)(_MonoMethod* method,
bool full);
297 empty_func_name[0] =
'\0';
298#if defined(ARCANE_OS_LINUX)
299 void* handle = dlopen(0, RTLD_LAZY);
303 m_mono_jit_info_get_code_start_ptr = (mono_jit_info_get_code_start_func)(dlsym(handle,
"mono_jit_info_get_code_start"));
304 m_mono_domain_get_ptr = (mono_domain_get_func)(dlsym(handle,
"mono_domain_get"));
305 m_mono_jit_info_table_find_ptr = (mono_jit_info_table_find_func)(dlsym(handle,
"mono_jit_info_table_find"));
306 m_mono_pmip_ptr = (mono_pmip_func)(dlsym(handle,
"mono_pmip"));
307 m_mono_jit_info_get_method_ptr = (mono_jit_info_get_method_func)(dlsym(handle,
"mono_jit_info_get_method"));
308 m_mono_method_full_name_ptr = (mono_method_full_name_func)(dlsym(handle,
"mono_method_full_name"));
310 if (!m_mono_jit_info_get_code_start_ptr)
312 if (!m_mono_domain_get_ptr)
314 if (!m_mono_jit_info_table_find_ptr)
316 if (!m_mono_pmip_ptr)
318 if (!m_mono_jit_info_get_method_ptr)
320 if (!m_mono_method_full_name_ptr)
325 ~MonoFuncAddrGetter()
327#if defined(ARCANE_OS_LINUX)
336 char empty_func_name[1];
337 char* getInfo(
void* ip,
void** _start_addr)
341 char* func_name = empty_func_name;
342 _MonoDomain* d = (*m_mono_domain_get_ptr)();
343 _MonoJitInfo* ji = (*m_mono_jit_info_table_find_ptr)(d, ip);
345 void* start_addr = 0;
347 start_addr = (*m_mono_jit_info_get_code_start_ptr)(ji);
348 _MonoMethod* method = (*m_mono_jit_info_get_method_ptr)(ji);
349 func_name = (*m_mono_method_full_name_ptr)(method,
true);
354 *_start_addr = start_addr;
360 bool m_is_valid =
false;
361 mono_jit_info_get_code_start_func m_mono_jit_info_get_code_start_ptr =
nullptr;
362 mono_domain_get_func m_mono_domain_get_ptr =
nullptr;
363 mono_jit_info_table_find_func m_mono_jit_info_table_find_ptr =
nullptr;
364 mono_pmip_func m_mono_pmip_ptr =
nullptr;
365 mono_jit_info_get_method_func m_mono_jit_info_get_method_ptr =
nullptr;
366 mono_method_full_name_func m_mono_method_full_name_ptr =
nullptr;
367 void* m_handle =
nullptr;
373static std::atomic<Int32> global_in_malloc;
375#ifdef ARCANE_USE_MALLOC_HOOK
379 void* (*my_old_malloc_hook)(size_t,
const void*);
380 void (*my_old_free_hook)(
void*,
const void*);
381 void* (*my_old_realloc_hook)(
void* __ptr,
size_t __size, __const
void*);
386extern void* prof_malloc_hook(
size_t size,
const void* caller);
387extern void prof_free_hook(
void* ptr,
const void* caller);
388extern void* prof_realloc_hook(
void* __ptr,
size_t __size, __const
void*);
393extern ARCANE_STD_EXPORT
void _pushHook()
395 __malloc_hook = my_old_malloc_hook;
396 __free_hook = my_old_free_hook;
397 __realloc_hook = my_old_realloc_hook;
400extern ARCANE_STD_EXPORT
void _popHook()
402 __malloc_hook = prof_malloc_hook;
403 __free_hook = prof_free_hook;
404 __realloc_hook = prof_realloc_hook;
407void* prof_malloc_hook(
size_t size,
const void* )
411 void* r = malloc(size);
417void prof_free_hook(
void* ptr,
const void* )
424void* prof_realloc_hook(
void* ptr,
size_t size,
const void* )
428 void* r = realloc(ptr, size);
434void _profInitMallocHook()
436 global_in_malloc = 0;
437 my_old_malloc_hook = __malloc_hook;
438 __malloc_hook = prof_malloc_hook;
439 my_old_free_hook = __free_hook;
440 __free_hook = prof_free_hook;
441 my_old_realloc_hook = __realloc_hook;
442 __realloc_hook = prof_realloc_hook;
445void _profRestoreMallocHook()
447 __free_hook = my_old_free_hook;
448 __malloc_hook = my_old_malloc_hook;
449 __realloc_hook = my_old_realloc_hook;
452void _profInitMallocHook()
455void _profRestoreMallocHook()
475 _getDemangledName(
const char* true_func_name,
char* demangled_buf,
size_t demangled_buf_len)
477 if (demangled_buf_len <= 1)
478 return true_func_name;
479 size_t len = demangled_buf_len - 1;
481 const char* buf =
nullptr;
483 buf = abi::__cxa_demangle(true_func_name, demangled_buf, &len, &dstatus);
486 buf = true_func_name;
497, m_default_func_info_provider(new NullFuncInfoProvider())
498, m_func_info_provider(m_default_func_info_provider)
500 for (
Integer i = 0; i < MAX_COUNTER; ++i)
506 m_mono_func_getter =
new MonoFuncAddrGetter();
507 if (!m_mono_func_getter->isValid()) {
508 delete m_mono_func_getter;
509 m_mono_func_getter = 0;
513#ifdef ARCANE_HAS_PACKAGE_LIBUNWIND
514 m_libunwind_func_info_provider =
new LibUnwindFuncInfos();
515 m_use_libunwind =
true;
517#ifdef ARCANE_HAS_GLIBC_BACKTRACE
518 m_backtrace_func_info_provider =
new BacktraceFuncInfos();
528 delete m_default_func_info_provider;
529 delete m_backtrace_func_info_provider;
530 delete m_libunwind_func_info_provider;
531 delete m_mono_func_getter;
542 ProfFuncInfo* fi = &m_func_info_buffer[m_current_func_info];
543 fi->setIndex(m_current_func_info);
544 ++m_current_func_info;
556 info() <<
"DÉBUT DU PROFILAGE";
562 _profInitMallocHook();
566 info() <<
"STACK_UNWIND=" << stack_unwinder_str;
567 if (stack_unwinder_str ==
"backtrace") {
568 m_use_backtrace =
true;
569 m_use_libunwind =
false;
571 m_func_info_provider = m_default_func_info_provider;
573 m_func_info_provider = m_backtrace_func_info_provider;
574 else if (m_use_libunwind)
575 m_func_info_provider = m_libunwind_func_info_provider;
576 info() <<
"Démarrage du profilage : use_backtrace=" << m_use_backtrace
577 <<
" use_libunwind=" << m_use_libunwind
578 <<
" has_mono=" << m_mono_func_getter;
587 m_is_started =
false;
588 _profRestoreMallocHook();
593 for (
Int32 i = 0, n = m_current_func_info; i < n; ++i) {
594 ProfFuncInfo& pfi = m_func_info_buffer[i];
595 if (!pfi.hasFuncName())
596 m_func_info_provider->fillFuncName(pfi);
614setFunctionDepth(
int v)
617 m_function_depth = v;
634 int global_nb_in_handler = 0;
638addEvent(
void* address,
int overflow_event[MAX_COUNTER],
int nb_overflow_event)
640 static bool is_in_handler =
false;
643 ++global_nb_in_handler;
646 is_in_handler =
true;
647 if (m_use_backtrace) {
649#ifdef ARCANE_HAS_GLIBC_BACKTRACE
650 BacktraceStackInfo stack_info((BacktraceFuncInfos*)m_backtrace_func_info_provider);
651 _addEvent(address, overflow_event, nb_overflow_event, stack_info, m_function_depth + 2);
654 else if (m_use_libunwind) {
655#ifdef ARCANE_HAS_PACKAGE_LIBUNWIND
656 LibUnwindStackInfo stack_info((LibUnwindFuncInfos*)m_libunwind_func_info_provider);
657 _addEvent(address, overflow_event, nb_overflow_event, stack_info, m_function_depth + 1);
660 is_in_handler =
false;
667_sortFunctions(std::set<ProfFuncInfo*, ProfFuncComparer>& sorted_func)
669 for (
const auto& x : m_func_map)
671 sorted_func.insert(x.second);
678_storeAddress(
void* address,
bool is_counter0,
int overflow_event[MAX_COUNTER],
int nb_overflow_event,
679 bool* do_add,
bool* do_stack,
bool* func_already_added)
682 ProfInfos::AddrMap::iterator v = m_addr_map.find(address);
683 if (v != m_addr_map.end()) {
684 ProfAddrInfo& ai = v->second;
685 for (
int i = 0; i < nb_overflow_event; ++i)
686 ++ai.m_counters[overflow_event[i]];
687 if (ai.m_func_info) {
688 for (
int i = 0; i < nb_overflow_event; ++i)
689 ++ai.m_func_info->m_counters[overflow_event[i]];
690 *func_already_added =
true;
693 if (m_total_event > m_nb_event_before_getting_stack) {
694 if ((ai.m_func_info->m_counters[0] * 100) > m_total_event) {
695 ai.m_func_info->m_do_stack =
true;
710_addEvent(
void* address,
int overflow_event[MAX_COUNTER],
int nb_overflow_event,
711 IStackInfoProvider& stack_info,
Integer function_depth)
717 if (global_in_malloc != 0) {
722 bool is_counter0 =
false;
724 for (
int i = 0; i < nb_overflow_event; ++i) {
725 if (overflow_event[i] == 0)
727 if (overflow_event[i] < 0 || overflow_event[i] >= MAX_COUNTER)
728 std::cerr <<
"arcane_papi_handler: EVENT ERROR n=" << overflow_event[i] <<
'\n';
731 bool do_stack =
false;
733 bool func_already_added =
false;
734 _storeAddress(address, is_counter0, overflow_event, nb_overflow_event,
735 &do_add, &do_stack, &func_already_added);
737 if (do_add || do_stack) {
738 ProfAddrInfo papi_address_info;
739 ProfStackInfo papi_stack_info;
740 for (
int i = 0; i < nb_overflow_event; ++i)
741 ++papi_address_info.m_counters[overflow_event[i]];
743 stack_info.fillStack(function_depth);
745 for (
Integer index = function_depth, nb_index = stack_info.nbIndex(); index < nb_index; ++index) {
746 intptr_t proc_start = stack_info.functionStartAddress(index);
748 ProfInfos::FuncMap::iterator func = m_func_map.find(proc_start);
749 ProfFuncInfo* papi_func_info =
nullptr;
750 if (func == m_func_map.end()) {
751 if (m_current_func_info >= MAX_FUNC) {
752 std::cerr <<
"arcane_papi_handler: MAX_FUNC atteint !\n";
755 papi_func_info = _getNextFuncInfo();
756 papi_address_info.m_func_info = papi_func_info;
757 Int32 func_index = papi_func_info->index();
758 stack_info.setFunc(func_index, index);
759 m_func_map.insert(ProfInfos::FuncMap::value_type(proc_start, papi_func_info));
762 papi_func_info = func->second;
765 if (index < (MAX_STACK + function_depth))
766 papi_stack_info.m_funcs_info_indexes[index - function_depth] = papi_func_info->index();
767 if (index == function_depth) {
768 papi_address_info.m_func_info = papi_func_info;
769 if (!func_already_added)
770 for (
int i = 0; i < nb_overflow_event; ++i)
771 ++papi_func_info->m_counters[overflow_event[i]];
772 if (!papi_func_info->m_do_stack || !is_counter0)
780 ProfInfos::StackMap::iterator st = m_stack_map.find(papi_stack_info);
781 if (st != m_stack_map.end()) {
785 m_stack_map.insert(ProfInfos::StackMap::value_type(papi_stack_info, 1));
788 m_addr_map.insert(ProfInfos::AddrMap::value_type(address, papi_address_info));
798_getFunc(
void* addr, FuncAddrInfo& info)
800#ifdef ARCANE_OS_LINUX
802 int r = dladdr(addr, &dl_info);
803 info.func_name =
"unknown";
809 info.start_addr = dl_info.dli_saddr;
810 if (dl_info.dli_sname) {
811 info.func_name = dl_info.dli_sname;
815 if (m_mono_func_getter) {
816 void* start_addr = 0;
817 char* func_name = m_mono_func_getter->getInfo(addr, &start_addr);
818 if (func_name && start_addr) {
819 info.start_addr = start_addr;
820 info.func_name = func_name;
834 ProfInfos* global_infos =
this;
836 ProfInfos::AddrMap::iterator begin = global_infos->m_addr_map.begin();
837 for (; begin != global_infos->m_addr_map.end(); ++begin) {
838 for (
Integer i = 0; i < MAX_COUNTER; ++i)
839 begin->second.m_counters[i] = 0;
843 ProfInfos::FuncMap::iterator begin = global_infos->m_func_map.begin();
844 for (; begin != global_infos->m_func_map.end(); ++begin) {
845 ProfFuncInfo* pf = begin->second;
846 for (
Integer i = 0; i < MAX_COUNTER; ++i)
847 pf->m_counters[i] = 0;
857printInfos(
bool dump_file)
859 ProfInfos* global_infos =
this;
861 Int64 total_event = 1;
865 info() <<
" PROCESS_ID = " << process_id;
866 info() <<
" NB ADDRESS MAP = " << global_infos->m_addr_map.size();
867 info() <<
" NB FUNC MAP = " << global_infos->m_func_map.size();
868 info() <<
" NB STACK MAP = " << global_infos->m_stack_map.size();
869 info() <<
" TOTAL STACK = " << global_infos->m_total_stack;
871 ProfInfos::AddrMap::const_iterator begin = global_infos->m_addr_map.begin();
872 for (; begin != global_infos->m_addr_map.end(); ++begin) {
873 Int64 nb_event = begin->second.m_counters[0];
874 total_event += nb_event;
875 Int64 nb_fp = begin->second.m_counters[2];
880 ProfInfos::FuncMap::const_iterator begin = global_infos->m_func_map.begin();
881 Int64 total_func_event = 0;
882 Int64 total_func_fp = 0;
883 for (; begin != global_infos->m_func_map.end(); ++begin) {
884 ProfFuncInfo* pf = begin->second;
885 Int64 nb_event = pf->m_counters[0];
886 total_func_event += nb_event;
887 Int64 nb_fp = pf->m_counters[2];
888 total_func_fp += nb_fp;
890 info() <<
" FUNC EVENT=" << total_func_event;
891 info() <<
" FUNC FP=" << total_func_fp;
895 StringBuilder sfile_name =
"profiling.addr";
896 sfile_name += process_id;
897 sfile_name +=
".xml";
898 String file_name = sfile_name;
899 std::ofstream ofile(file_name.localstr());
900 ofile <<
"<?xml version='1.0'?>\n";
901 ofile <<
"<addresses>\n";
902 ProfInfos::AddrMap::const_iterator begin = global_infos->m_addr_map.begin();
903 for (; begin != global_infos->m_addr_map.end(); ++begin) {
904 void* addr = begin->first;
905 const ProfAddrInfo& pa = begin->second;
906 ProfFuncInfo* fi = pa.m_func_info;
908 ofile <<
"<addr addr='" << addr <<
"'"
909 <<
" count='" << pa.m_counters[0] <<
"'"
910 <<
" fi='" << fi <<
"'"
911 <<
" fi_count='" << fi->m_counters[0] <<
"'"
912 <<
" func='" << fi->m_func_name <<
"'"
916 ofile <<
"/<addresses>\n";
920 std::set<ProfFuncInfo*, ProfFuncComparer> sorted_func;
921 _sortFunctions(sorted_func);
923 const size_t NAME_BUF_SIZE = 8120;
924 char demangled_func_name[NAME_BUF_SIZE];
926 info() <<
" TOTAL EVENT = " << total_event;
927 info() <<
" TOTAL NB_IN_HANDLER = " << global_nb_in_handler;
928 Real nb_gflop = ((
Real)total_fp * (
Real)m_period) * 1e-09;
929 info() <<
" TOTAL FP = " << total_fp <<
" (nb_giga_flip=" << nb_gflop <<
")";
930 info() <<
" RATIO FP/CYC = " << ((
Real)total_fp / (
Real)total_event);
931 info() <<
" " << Trace::Width(10) <<
"nb_event"
932 <<
" " << Trace::Width(5) <<
"%"
933 <<
" " << Trace::Width(5) <<
"cum%"
934 <<
" " << Trace::Width(12) <<
"event1"
935 <<
" " << Trace::Width(12) <<
"event2"
936 <<
" " << Trace::Width(12) <<
"event3"
938 <<
" " <<
"function";
940 Int64 cumulative_nb_event = 0;
941 for (ProfFuncInfo* pfi : sorted_func) {
942 const char* func_name = pfi->m_func_name;
943 const char* buf = _getDemangledName(func_name, demangled_func_name, NAME_BUF_SIZE);
944 Int64 nb_event = pfi->m_counters[0];
945 cumulative_nb_event += nb_event;
946 Int64 cumulative_total_percent = (cumulative_nb_event * 1000) / total_event;
947 Int64 total_percent = (nb_event * 1000) / total_event;
948 Int64 cumulative_percent = (cumulative_total_percent / 10);
949 Int64 percent = (total_percent / 10);
950 info() <<
" " << Trace::Width(10) << nb_event
951 <<
" " << Trace::Width(3) << percent <<
"." << (total_percent % 10)
952 <<
" " << Trace::Width(3) << cumulative_percent <<
"." << (cumulative_total_percent % 10)
953 <<
" " << Trace::Width(12) << pfi->m_counters[0]
954 <<
" " << Trace::Width(12) << pfi->m_counters[1]
955 <<
" " << Trace::Width(12) << pfi->m_counters[2]
956 <<
" " << pfi->m_do_stack
958 if (total_percent < 5 && index > 20)
966 UniqueArray<SortedProfStackInfo> sorted_stacks;
967 for (
const auto& x : global_infos->m_stack_map) {
968 const ProfStackInfo& psi = x.first;
969 Int64 nb_stack = x.second;
972 std::sort(std::begin(sorted_stacks), std::end(sorted_stacks));
976 ofile.open(file_name.localstr());
978 for (
const auto& x : sorted_stacks) {
979 const ProfStackInfo& psi = x.stackInfo();
980 Int64 nb_stack = x.nbCount();
983 ofile <<
" Stack nb=" << nb_stack <<
'\n';
984 for (
Integer z = 0; z < MAX_STACK; ++z) {
985 Int32 fidx = psi.m_funcs_info_indexes[z];
987 ProfFuncInfo& pfi = _funcInfoFromIndex(fidx);
988 const char* func_name = pfi.m_func_name;
989 const char* buf = _getDemangledName(func_name, demangled_func_name, NAME_BUF_SIZE);
990 ofile <<
" " << buf <<
'\n';
1018 const size_t NAME_BUF_SIZE = 8192;
1019 char demangled_func_name[NAME_BUF_SIZE];
1020 ProfInfos* global_infos =
this;
1021 Int64 total_event = 1;
1026 ProfInfos::AddrMap::const_iterator begin = global_infos->m_addr_map.begin();
1027 for (; begin != global_infos->m_addr_map.end(); ++begin) {
1028 Int64 nb_event = begin->second.m_counters[0];
1029 total_event += nb_event;
1030 Int64 nb_fp = begin->second.m_counters[2];
1035 pkt.add(total_event);
1037 pkt.add((
Int64)m_period);
1038 info() <<
"[ProfInfos::getInfos] total_event=" << total_event <<
", total_fp=" << total_fp <<
", m_period=" << m_period;
1040 std::set<ProfFuncInfo*, ProfFuncComparer> sorted_func;
1041 _sortFunctions(sorted_func);
1044 pkt.add((
Int64)index);
1047 for (ProfFuncInfo* pfi : sorted_func) {
1048 const char* func_name = pfi->m_func_name;
1049 const char* buf = _getDemangledName(func_name, demangled_func_name, NAME_BUF_SIZE);
1050 Int64 nb_event = pfi->m_counters[0];
1052 Int64 total_percent = (nb_event * 1000) / total_event;
1053 pkt.add(total_percent);
1054 pkt.add(pfi->m_counters[0]);
1055 pkt.add(pfi->m_counters[1]);
1056 pkt.add(pfi->m_counters[2]);
1058 Int64 mx = strlen(buf);
1060 for (
Int64 i = 0; i < mx; i += 8)
1061 pkt.add(*(
Int64*)&buf[i]);
1063 if (total_percent < 1 && index > 16)
1067 pkt[5] = (
Int64)(index);
1068 info() <<
"[ProfInfos::getInfos] index @[4] =" << pkt[5];
1080 ProfInfos* global_infos =
this;
1082 Int64 total_event = 1;
1083 for (
const auto& x : global_infos->m_addr_map) {
1084 Int64 nb_event = x.second.m_counters[0];
1085 total_event += nb_event;
1090 writer.write(
"ProcessId", (
Int64)process_id);
1091 writer.write(
"NbAddressMap", global_infos->m_addr_map.size());
1092 writer.write(
"NbFuncMap", global_infos->m_func_map.size());
1093 writer.write(
"NbStackMap", global_infos->m_stack_map.size());
1094 writer.write(
"TotalStack", global_infos->m_total_stack);
1095 writer.write(
"TotalEvent", total_event);
1098 std::set<ProfFuncInfo*, ProfFuncComparer> sorted_func;
1099 _sortFunctions(sorted_func);
1101 const size_t NAME_BUF_SIZE = 8192;
1102 char demangled_func_name[NAME_BUF_SIZE];
1106 writer.writeKey(
"Functions");
1107 writer.beginArray();
1108 for (
Int32 i = 0, n = m_current_func_info; i < n; ++i) {
1109 const ProfFuncInfo& pfi = m_func_info_buffer[i];
1110 const char* func_name = pfi.m_func_name;
1111 const char* buf = _getDemangledName(func_name, demangled_func_name, NAME_BUF_SIZE);
1114 JSONWriter::Object o(writer);
1115 writer.write(
"Index", (
Int64)pfi.index());
1116 writer.write(
"Name", func_name);
1117 writer.write(
"DemangledName", buf);
1127 writer.writeKey(
"SortedFuncTimes");
1128 writer.beginArray();
1129 for (ProfFuncInfo* pfi : sorted_func) {
1130 const char* func_name = pfi->m_func_name;
1131 const char* buf = _getDemangledName(func_name, demangled_func_name, NAME_BUF_SIZE);
1133 JSONWriter::Object o(writer);
1134 writer.write(
"Index", (
Int64)(pfi->index()));
1135 writer.write(
"Name", buf);
1147 UniqueArray<SortedProfStackInfo> sorted_stacks;
1148 for (
const auto& x : global_infos->m_stack_map) {
1149 const ProfStackInfo& psi = x.first;
1150 Int64 nb_stack = x.second;
1153 std::sort(std::begin(sorted_stacks), std::end(sorted_stacks));
1155 writer.writeKey(
"StackMap");
1156 writer.beginArray();
1157 for (
const auto& x : sorted_stacks) {
1158 const ProfStackInfo& psi = x.stackInfo();
1159 Int64 nb_stack = x.nbCount();
1163 JSONWriter::Object o(writer);
1164 writer.write(
"Count", nb_stack);
1167 writer.writeKey(
"StackNames");
1168 writer.beginArray();
1169 for (
Integer z = 0; z < MAX_STACK; ++z) {
1170 Int32 fidx = psi.m_funcs_info_indexes[z];
1172 ProfFuncInfo& pfi = _funcInfoFromIndex(fidx);
1173 const char* func_name = pfi.m_func_name;
1174 const char* buf = _getDemangledName(func_name, demangled_func_name, NAME_BUF_SIZE);
1175 writer.writeValue(buf);
1178 writer.writeValue(String());
Fichier de configuration d'Arcane.
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Interface du gestionnaire de traces.
Interface pour récupérer les infos d'une pile d'appel.
Classe d'accès aux traces.
TraceMessage info() const
Flot pour un message d'information.
Integer len(const char *s)
Retourne la longueur de la chaîne s.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
double Real
Type représentant un réel.
std::int32_t Int32
Type entier signé sur 32 bits.