30 #ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H
31 #define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1
37 #if __cplusplus >= 201103L
38 #define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_C::unordered_map
39 #include <unordered_map>
41 #include <tr1/unordered_map>
42 #define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
65 typedef _GLIBCXX_IMPL_UNORDERED_MAP<std::string, std::string>
__env_t;
67 _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__env_t, __env);
70 _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__gnu_cxx::__mutex, __global_lock);
77 const char* __warning_id;
81 : __magnitude(0.0), __context(0), __warning_id(0) { }
85 : __magnitude(__m), __context(__c), __warning_id(__id),
86 __warning_message(__msg) { }
90 {
return __magnitude < __other.__magnitude; }
93 typedef std::_GLIBCXX_STD_C::vector<__warning_data> __warning_vector_t;
101 class __trace_list_to_slist;
102 class __trace_list_to_vector;
103 void __trace_vector_size_init();
104 void __trace_hashtable_size_init();
105 void __trace_hash_func_init();
106 void __trace_vector_to_list_init();
107 void __trace_list_to_slist_init();
108 void __trace_list_to_vector_init();
109 void __trace_map_to_unordered_map_init();
110 void __trace_vector_size_report(FILE*, __warning_vector_t&);
111 void __trace_hashtable_size_report(FILE*, __warning_vector_t&);
112 void __trace_hash_func_report(FILE*, __warning_vector_t&);
113 void __trace_vector_to_list_report(FILE*, __warning_vector_t&);
114 void __trace_list_to_slist_report(FILE*, __warning_vector_t&);
115 void __trace_list_to_vector_report(FILE*, __warning_vector_t&);
116 void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&);
120 const char* __env_var;
124 typedef std::_GLIBCXX_STD_C::vector<__cost_factor*> __cost_factor_vector;
126 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, 0);
127 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, 0);
128 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, 0);
129 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, 0);
130 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, 0);
131 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, 0);
132 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, 0);
134 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_shift_cost_factor,
135 {
"__vector_shift_cost_factor", 1.0});
136 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_iterate_cost_factor,
137 {
"__vector_iterate_cost_factor", 1.0});
138 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_resize_cost_factor,
139 {
"__vector_resize_cost_factor", 1.0});
140 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_shift_cost_factor,
141 {
"__list_shift_cost_factor", 0.0});
142 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_iterate_cost_factor,
143 {
"__list_iterate_cost_factor", 10.0});
144 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_resize_cost_factor,
145 {
"__list_resize_cost_factor", 0.0});
146 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_insert_cost_factor,
147 {
"__map_insert_cost_factor", 1.5});
148 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_erase_cost_factor,
149 {
"__map_erase_cost_factor", 1.5});
150 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_find_cost_factor,
151 {
"__map_find_cost_factor", 1});
152 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_iterate_cost_factor,
153 {
"__map_iterate_cost_factor", 2.3});
154 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_insert_cost_factor,
155 {
"__umap_insert_cost_factor", 12.0});
156 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_erase_cost_factor,
157 {
"__umap_erase_cost_factor", 12.0});
158 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_find_cost_factor,
159 {
"__umap_find_cost_factor", 10.0});
160 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_iterate_cost_factor,
161 {
"__umap_iterate_cost_factor", 1.7});
162 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor_vector*, __cost_factors, 0);
164 _GLIBCXX_PROFILE_DEFINE_DATA(
const char*, _S_trace_file_name,
165 _GLIBCXX_PROFILE_TRACE_PATH_ROOT);
166 _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_warn_count,
167 _GLIBCXX_PROFILE_MAX_WARN_COUNT);
168 _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_stack_depth,
169 _GLIBCXX_PROFILE_MAX_STACK_DEPTH);
170 _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_mem,
171 _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC);
175 {
return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); }
179 {
return _GLIBCXX_PROFILE_DATA(_S_max_mem); }
182 template<
typename __
object_info,
typename __stack_info>
189 : __object_table(10000), __stack_table(10000),
190 __stack_table_byte_size(0), __id(0) { }
194 void __add_object(__object_t
object, __object_info __info);
195 __object_info* __get_object_info(__object_t __object);
196 void __retire_object(__object_t __object);
197 void __write(FILE* __f);
198 void __collect_warnings(__warning_vector_t& __warnings);
201 __gnu_cxx::__mutex __object_table_lock;
202 __gnu_cxx::__mutex __stack_table_lock;
203 typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t,
204 __object_info> __object_table_t;
205 typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info,
207 __stack_hash> __stack_table_t;
208 __object_table_t __object_table;
209 __stack_table_t __stack_table;
210 std::size_t __stack_table_byte_size;
216 template<
typename __
object_info,
typename __stack_info>
221 for (
typename __stack_table_t::iterator __it
222 = __stack_table.begin(); __it != __stack_table.end(); ++__it)
225 (*__it).second.__advice()));
228 template<
typename __
object_info,
typename __stack_info>
230 __trace_base<__object_info, __stack_info>::
231 __add_object(__object_t __object, __object_info __info)
234 || __object_table.size() *
sizeof(__object_info) <= __max_mem())
236 this->__object_table_lock.lock();
237 __object_table.insert(
typename __object_table_t::
238 value_type(__object, __info));
239 this->__object_table_lock.unlock();
243 template<
typename __
object_info,
typename __stack_info>
245 __trace_base<__object_info, __stack_info>::
246 __get_object_info(__object_t __object)
251 this->__object_table_lock.lock();
252 typename __object_table_t::iterator __object_it
253 = __object_table.find(__object);
255 if (__object_it == __object_table.end())
257 this->__object_table_lock.unlock();
262 this->__object_table_lock.unlock();
263 return &__object_it->second;
267 template<
typename __
object_info,
typename __stack_info>
269 __trace_base<__object_info, __stack_info>::
270 __retire_object(__object_t __object)
272 this->__object_table_lock.lock();
273 this->__stack_table_lock.lock();
274 typename __object_table_t::iterator __object_it
275 = __object_table.find(__object);
277 if (__object_it != __object_table.end())
279 const __object_info& __info = __object_it->second;
280 const __stack_t& __stack = __info.__stack();
281 typename __stack_table_t::iterator __stack_it
282 = __stack_table.find(__stack);
284 if (__stack_it == __stack_table.end())
287 if (__max_mem() == 0 || __stack_table_byte_size < __max_mem())
289 __stack_table_byte_size
290 += (
sizeof(__instruction_address_t) * __size(__stack)
291 +
sizeof(__stack) +
sizeof(__stack_info));
293 __stack_info(__info)));
299 __stack_it->second.__merge(__info);
302 __object_table.erase(__object);
305 this->__object_table_lock.unlock();
306 this->__stack_table_lock.unlock();
309 template<
typename __
object_info,
typename __stack_info>
311 __trace_base<__object_info, __stack_info>::
314 for (
typename __stack_table_t::iterator __it
315 = __stack_table.begin(); __it != __stack_table.end(); ++__it)
316 if (__it->second.__is_valid())
318 std::fprintf(__f, __id);
319 std::fprintf(__f,
"|");
320 __gnu_profile::__write(__f, __it->first);
321 std::fprintf(__f,
"|");
322 __it->second.__write(__f);
327 __env_to_size_t(
const char* __env_var, std::size_t __default_value)
329 char* __env_value = std::getenv(__env_var);
333 long __converted_value = std::strtol(__env_value, 0, 10);
334 if (errno || __converted_value < 0)
337 "Bad value for environment variable '%s'.\n",
342 return static_cast<std::size_t
>(__converted_value);
345 return __default_value;
349 __set_max_stack_trace_depth()
351 _GLIBCXX_PROFILE_DATA(_S_max_stack_depth)
352 = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR,
353 _GLIBCXX_PROFILE_DATA(_S_max_stack_depth));
359 _GLIBCXX_PROFILE_DATA(_S_max_mem)
360 = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR,
361 _GLIBCXX_PROFILE_DATA(_S_max_mem));
365 __log_magnitude(
float __f)
367 const float __log_base = 10.0;
377 while (__f > __log_base)
382 return __sign * __result;
386 __open_output_file(
const char* __extension)
389 std::size_t __root_len
390 = __builtin_strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
391 std::size_t __ext_len = __builtin_strlen(__extension);
392 char* __file_name =
new char[__root_len + 1 + __ext_len + 1];
393 __builtin_memcpy(__file_name,
394 _GLIBCXX_PROFILE_DATA(_S_trace_file_name),
396 *(__file_name + __root_len) =
'.';
397 __builtin_memcpy(__file_name + __root_len + 1,
398 __extension, __ext_len + 1);
400 FILE* __out_file = std::fopen(__file_name,
"w");
403 std::fprintf(stderr,
"Could not open trace file '%s'.\n",
408 delete[] __file_name;
420 operator()(
const __warning_data& __info)
422 std::fprintf(__file, __info.__warning_id);
423 std::fprintf(__file,
": improvement = %d",
424 __log_magnitude(__info.__magnitude));
425 std::fprintf(__file,
": call stack = ");
426 __gnu_profile::__write(__file, __info.__context);
427 std::fprintf(__file,
": advice = %s\n",
428 __info.__warning_message.c_str());
442 _GLIBCXX_PROFILE_DATA(__global_lock).lock();
444 __warning_vector_t __warnings, __top_warnings;
446 FILE* __raw_file = __open_output_file(
"raw");
447 __trace_vector_size_report(__raw_file, __warnings);
448 __trace_hashtable_size_report(__raw_file, __warnings);
449 __trace_hash_func_report(__raw_file, __warnings);
450 __trace_vector_to_list_report(__raw_file, __warnings);
451 __trace_list_to_slist_report(__raw_file, __warnings);
452 __trace_list_to_vector_report(__raw_file, __warnings);
453 __trace_map_to_unordered_map_report(__raw_file, __warnings);
454 std::fclose(__raw_file);
457 std::size_t __cutoff =
std::min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count),
459 __top_n(__warnings, __top_warnings, __cutoff);
461 FILE* __warn_file = __open_output_file(
"txt");
462 __for_each(__top_warnings.begin(), __top_warnings.end(),
463 __warn(__warn_file));
464 std::fclose(__warn_file);
466 _GLIBCXX_PROFILE_DATA(__global_lock).unlock();
472 char* __env_trace_file_name = std::getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
474 if (__env_trace_file_name)
475 _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name;
478 std::fclose(__open_output_file(
"txt"));
482 __set_max_warn_count()
484 char* __env_max_warn_count_str
485 = std::getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
487 if (__env_max_warn_count_str)
488 _GLIBCXX_PROFILE_DATA(_S_max_warn_count)
489 =
static_cast<std::size_t
>(std::atoi(__env_max_warn_count_str));
493 __read_cost_factors()
495 std::string __conf_file_name(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
496 __conf_file_name +=
".conf";
498 std::ifstream __conf_file(__conf_file_name.c_str());
500 if (__conf_file.is_open())
508 if (__line.
length() <= 0 || __line[__i] ==
'#')
516 std::string::size_type __pos = __line.
find(
"=");
521 _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value;
525 struct __cost_factor_writer
529 __cost_factor_writer(FILE* __f)
533 operator() (
const __cost_factor* __factor)
534 { std::fprintf(__file,
"%s = %f\n", __factor->__env_var,
535 __factor->__value); }
539 __write_cost_factors()
541 FILE* __file = __open_output_file(
"conf.out");
542 __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->
begin(),
543 _GLIBCXX_PROFILE_DATA(__cost_factors)->
end(),
544 __cost_factor_writer(__file));
548 struct __cost_factor_setter
551 operator()(__cost_factor* __factor)
554 const char* __env_value = std::getenv(__factor->__env_var);
559 __env_t::iterator __it
560 = _GLIBCXX_PROFILE_DATA(__env).find(__factor->__env_var);
561 if (__it != _GLIBCXX_PROFILE_DATA(__env).
end())
562 __env_value = (*__it).second.c_str();
566 __factor->__value = std::atof(__env_value);
573 _GLIBCXX_PROFILE_DATA(__cost_factors) =
new __cost_factor_vector;
574 _GLIBCXX_PROFILE_DATA(__cost_factors)->
575 push_back(&_GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor));
576 _GLIBCXX_PROFILE_DATA(__cost_factors)->
577 push_back(&_GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor));
578 _GLIBCXX_PROFILE_DATA(__cost_factors)->
579 push_back(&_GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor));
580 _GLIBCXX_PROFILE_DATA(__cost_factors)->
581 push_back(&_GLIBCXX_PROFILE_DATA(__list_shift_cost_factor));
582 _GLIBCXX_PROFILE_DATA(__cost_factors)->
583 push_back(&_GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor));
584 _GLIBCXX_PROFILE_DATA(__cost_factors)->
585 push_back(&_GLIBCXX_PROFILE_DATA(__list_resize_cost_factor));
586 _GLIBCXX_PROFILE_DATA(__cost_factors)->
587 push_back(&_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor));
588 _GLIBCXX_PROFILE_DATA(__cost_factors)->
589 push_back(&_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor));
590 _GLIBCXX_PROFILE_DATA(__cost_factors)->
591 push_back(&_GLIBCXX_PROFILE_DATA(__map_find_cost_factor));
592 _GLIBCXX_PROFILE_DATA(__cost_factors)->
593 push_back(&_GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor));
594 _GLIBCXX_PROFILE_DATA(__cost_factors)->
595 push_back(&_GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor));
596 _GLIBCXX_PROFILE_DATA(__cost_factors)->
597 push_back(&_GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor));
598 _GLIBCXX_PROFILE_DATA(__cost_factors)->
599 push_back(&_GLIBCXX_PROFILE_DATA(__umap_find_cost_factor));
600 _GLIBCXX_PROFILE_DATA(__cost_factors)->
601 push_back(&_GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor));
602 __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->
begin(),
603 _GLIBCXX_PROFILE_DATA(__cost_factors)->
end(),
604 __cost_factor_setter());
608 __profcxx_init_unconditional()
610 _GLIBCXX_PROFILE_DATA(__global_lock).lock();
614 __set_max_warn_count();
616 if (_GLIBCXX_PROFILE_DATA(_S_max_warn_count) == 0)
620 __set_max_stack_trace_depth();
623 __read_cost_factors();
624 __set_cost_factors();
625 __write_cost_factors();
627 __trace_vector_size_init();
628 __trace_hashtable_size_init();
629 __trace_hash_func_init();
630 __trace_vector_to_list_init();
631 __trace_list_to_slist_init();
632 __trace_list_to_vector_init();
633 __trace_map_to_unordered_map_init();
641 _GLIBCXX_PROFILE_DATA(__global_lock).unlock();
652 __profcxx_init_unconditional();
GNU profile code for public use.
Base class for all trace producers.
Hash function for summary trace using call stack as index.
std::::unordered_map< std::string, std::string > __env_t
Internal environment. Values can be set one of two ways: 1. In config file "var = value"...
auto end(_Container &__cont) -> decltype(__cont.end())
Return an iterator pointing to one past the last element of the container.
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters.
Hashtable size instrumentation trace producer.
size_type find_first_not_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character not in string.
Vector-to-list instrumentation producer.
basic_string substr(size_type __pos=0, size_type __n=npos) const
Get a substring.
iterator begin() noexcept
constexpr pair< typename __decay_and_strip< _T1 >::__type, typename __decay_and_strip< _T2 >::__type > make_pair(_T1 &&__x, _T2 &&__y)
A convenience wrapper for creating a pair from two objects.
size_type find_first_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character of string.
Hash performance instrumentation producer.
basic_istream< _CharT, _Traits > & getline(basic_istream< _CharT, _Traits > &__is, basic_string< _CharT, _Traits, _Alloc > &__str, _CharT __delim)
Read a line from stream into a string.
void __report(void)
Final report method, registered with atexit.
Algorithms used by the profile extension.
size_type length() const noexcept
Returns the number of characters in the string, not including any null-termination.
bool __profcxx_init()
This function must be called by each instrumentation point.
Hashtable size instrumentation trace producer.
auto begin(_Container &__cont) -> decltype(__cont.begin())
Return an iterator pointing to the first element of the container.
size_type find(const _CharT *__s, size_type __pos, size_type __n) const
Find position of a C substring.
const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Data structures to represent a single profiling event.
Map-to-unordered_map instrumentation producer.
Representation of a warning.