15#include "arcane/utils/ArcanePrecomp.h"
17#include "arcane/utils/Array.h"
18#include "arcane/utils/String.h"
19#include "arcane/utils/StringBuilder.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/JSONWriter.h"
23#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() <<
"START PROFILING";
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() <<
"Start profiling: 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 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 cerr <<
"arcane_papi_handler: MAX_FUNC reached !\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());
Arcane configuration file.
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Interface to retrieve call stack information.
TraceMessage info() const
Flow for an information message.
Integer len(const char *s)
Returns the length of the string s.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Array< Int64 > Int64Array
Dynamic one-dimensional array of 64-bit integers.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
double Real
Type representing a real number.
std::int32_t Int32
Signed integer type of 32 bits.