30 #ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H
31 #define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1
37 #if __cplusplus >= 201103L
39 #define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_C::unordered_map
41 #include <tr1/unordered_map>
42 #define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
55 namespace __gnu_profile
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_mutex);
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&);
117 void __trace_vector_size_free();
118 void __trace_hashtable_size_free();
119 void __trace_hash_func_free();
120 void __trace_vector_to_list_free();
121 void __trace_list_to_slist_free();
122 void __trace_list_to_vector_free();
123 void __trace_map_to_unordered_map_free();
127 const char* __env_var;
131 typedef std::_GLIBCXX_STD_C::vector<__cost_factor*> __cost_factor_vector;
133 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, 0);
134 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, 0);
135 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, 0);
136 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, 0);
137 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, 0);
138 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, 0);
139 _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, 0);
141 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_shift_cost_factor,
142 {
"__vector_shift_cost_factor", 1.0});
143 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_iterate_cost_factor,
144 {
"__vector_iterate_cost_factor", 1.0});
145 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_resize_cost_factor,
146 {
"__vector_resize_cost_factor", 1.0});
147 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_shift_cost_factor,
148 {
"__list_shift_cost_factor", 0.0});
149 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_iterate_cost_factor,
150 {
"__list_iterate_cost_factor", 10.0});
151 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_resize_cost_factor,
152 {
"__list_resize_cost_factor", 0.0});
153 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_insert_cost_factor,
154 {
"__map_insert_cost_factor", 1.5});
155 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_erase_cost_factor,
156 {
"__map_erase_cost_factor", 1.5});
157 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_find_cost_factor,
158 {
"__map_find_cost_factor", 1});
159 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_iterate_cost_factor,
160 {
"__map_iterate_cost_factor", 2.3});
161 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_insert_cost_factor,
162 {
"__umap_insert_cost_factor", 12.0});
163 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_erase_cost_factor,
164 {
"__umap_erase_cost_factor", 12.0});
165 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_find_cost_factor,
166 {
"__umap_find_cost_factor", 10.0});
167 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_iterate_cost_factor,
168 {
"__umap_iterate_cost_factor", 1.7});
169 _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor_vector*, __cost_factors, 0);
171 _GLIBCXX_PROFILE_DEFINE_DATA(
const char*, _S_trace_file_name,
172 _GLIBCXX_PROFILE_TRACE_PATH_ROOT);
173 _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_warn_count,
174 _GLIBCXX_PROFILE_MAX_WARN_COUNT);
175 _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_stack_depth,
176 _GLIBCXX_PROFILE_MAX_STACK_DEPTH);
177 _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_mem,
178 _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC);
182 {
return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); }
186 {
return _GLIBCXX_PROFILE_DATA(_S_max_mem); }
189 template<
typename __
object_info,
typename __stack_info>
196 : __objects_byte_size(0), __stack_table(10000),
197 __stack_table_byte_size(0), __id(0) { }
201 for (
typename __stack_table_t::iterator __it
202 = __stack_table.begin(); __it != __stack_table.end(); ++__it)
206 __object_info* __add_object(__stack_t __stack);
207 void __retire_object(__object_info* __info);
208 void __write(FILE* __f);
209 void __collect_warnings(__warning_vector_t& __warnings);
213 __gnu_cxx::__mutex __trace_mutex;
214 typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info,
217 std::size_t __objects_byte_size;
218 __stack_table_t __stack_table;
219 std::size_t __stack_table_byte_size;
225 template<
typename __
object_info,
typename __stack_info>
236 if (__max_mem() != 0 && __objects_byte_size >= __max_mem())
242 __object_info* __ret =
new(std::nothrow) __object_info(__stack);
249 __objects_byte_size +=
sizeof(__object_info);
253 template<
typename __
object_info,
typename __stack_info>
255 __trace_base<__object_info, __stack_info>::
256 __retire_object(__object_info* __obj_info)
263 const __object_info& __info = *__obj_info;
264 __stack_t __stack = __info.__stack();
265 typename __stack_table_t::iterator __stack_it
266 = __stack_table.find(__stack);
268 if (__stack_it == __stack_table.end())
271 if (__max_mem() == 0 || __stack_table_byte_size < __max_mem())
273 __stack_table_byte_size
274 += (
sizeof(__instruction_address_t) * __size(__stack)
275 +
sizeof(__stack) +
sizeof(__stack_info));
277 __stack_info(__info)));
285 __stack_it->second.__merge(__info);
290 __objects_byte_size -=
sizeof(__object_info);
293 template<
typename __
object_info,
typename __stack_info>
295 __trace_base<__object_info, __stack_info>::
298 for (
typename __stack_table_t::iterator __it
299 = __stack_table.begin(); __it != __stack_table.end(); ++__it)
300 if (__it->second.__is_valid())
302 std::fprintf(__f, __id);
303 std::fprintf(__f,
"|");
304 __gnu_profile::__write(__f, __it->first);
305 std::fprintf(__f,
"|");
306 __it->second.__write(__f);
310 template<
typename __
object_info,
typename __stack_info>
312 __trace_base<__object_info, __stack_info>::
313 __collect_warnings(__warning_vector_t& __warnings)
315 for (
typename __stack_table_t::iterator __it
316 = __stack_table.begin(); __it != __stack_table.end(); ++__it)
317 __warnings.push_back(__warning_data(__it->second.__magnitude(),
319 __it->second.__advice()));
322 template<
typename __
object_info,
typename __stack_info>
324 __trace_report(__trace_base<__object_info, __stack_info>* __cont,
325 FILE* __f, __warning_vector_t& __warnings)
329 __cont->__collect_warnings(__warnings);
330 __cont->__write(__f);
335 __env_to_size_t(
const char* __env_var, std::size_t __default_value)
337 char* __env_value = std::getenv(__env_var);
341 long __converted_value = std::strtol(__env_value, 0, 10);
342 if (errno || __converted_value < 0)
345 "Bad value for environment variable '%s'.\n",
350 return static_cast<std::size_t
>(__converted_value);
353 return __default_value;
357 __set_max_stack_trace_depth()
359 _GLIBCXX_PROFILE_DATA(_S_max_stack_depth)
360 = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR,
361 _GLIBCXX_PROFILE_DATA(_S_max_stack_depth));
367 _GLIBCXX_PROFILE_DATA(_S_max_mem)
368 = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR,
369 _GLIBCXX_PROFILE_DATA(_S_max_mem));
373 __log_magnitude(
float __f)
375 const float __log_base = 10.0;
385 while (__f > __log_base)
390 return __sign * __result;
394 __open_output_file(
const char* __extension)
397 std::size_t __root_len
398 = __builtin_strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
399 std::size_t __ext_len = __builtin_strlen(__extension);
400 char* __file_name =
new char[__root_len + 1 + __ext_len + 1];
401 __builtin_memcpy(__file_name,
402 _GLIBCXX_PROFILE_DATA(_S_trace_file_name),
404 *(__file_name + __root_len) =
'.';
405 __builtin_memcpy(__file_name + __root_len + 1,
406 __extension, __ext_len + 1);
408 FILE* __out_file = std::fopen(__file_name,
"w");
411 std::fprintf(stderr,
"Could not open trace file '%s'.\n",
416 delete[] __file_name;
428 operator()(
const __warning_data& __info)
430 std::fprintf(__file, __info.__warning_id);
431 std::fprintf(__file,
": improvement = %d",
432 __log_magnitude(__info.__magnitude));
433 std::fprintf(__file,
": call stack = ");
434 __gnu_profile::__write(__file, __info.__context);
435 std::fprintf(__file,
": advice = %s\n",
436 __info.__warning_message.c_str());
452 __warning_vector_t __warnings, __top_warnings;
454 FILE* __raw_file = __open_output_file(
"raw");
455 __trace_vector_size_report(__raw_file, __warnings);
456 __trace_hashtable_size_report(__raw_file, __warnings);
457 __trace_hash_func_report(__raw_file, __warnings);
458 __trace_vector_to_list_report(__raw_file, __warnings);
459 __trace_list_to_slist_report(__raw_file, __warnings);
460 __trace_list_to_vector_report(__raw_file, __warnings);
461 __trace_map_to_unordered_map_report(__raw_file, __warnings);
462 std::fclose(__raw_file);
465 std::size_t __cutoff =
std::min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count),
467 __top_n(__warnings, __top_warnings, __cutoff);
469 FILE* __warn_file = __open_output_file(
"txt");
470 __for_each(__top_warnings.begin(), __top_warnings.end(),
471 __warn(__warn_file));
472 std::fclose(__warn_file);
480 __trace_map_to_unordered_map_free();
481 __trace_list_to_vector_free();
482 __trace_list_to_slist_free();
483 __trace_vector_to_list_free();
484 __trace_hash_func_free();
485 __trace_hashtable_size_free();
486 __trace_vector_size_free();
487 delete _GLIBCXX_PROFILE_DATA(__cost_factors);
493 char* __env_trace_file_name = std::getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
495 if (__env_trace_file_name)
496 _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name;
499 std::fclose(__open_output_file(
"txt"));
503 __set_max_warn_count()
505 char* __env_max_warn_count_str
506 = std::getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
508 if (__env_max_warn_count_str)
509 _GLIBCXX_PROFILE_DATA(_S_max_warn_count)
510 =
static_cast<std::size_t
>(std::atoi(__env_max_warn_count_str));
514 __read_cost_factors()
516 std::string __conf_file_name(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
517 __conf_file_name +=
".conf";
521 if (__conf_file.is_open())
529 if (__line.
length() <= 0 || __line[__i] ==
'#')
537 std::string::size_type __pos = __line.
find(
"=");
542 _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value;
546 struct __cost_factor_writer
550 __cost_factor_writer(FILE* __f)
554 operator() (
const __cost_factor* __factor)
555 { std::fprintf(__file,
"%s = %f\n", __factor->__env_var,
556 __factor->__value); }
560 __write_cost_factors()
562 FILE* __file = __open_output_file(
"conf.out");
563 __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->
begin(),
564 _GLIBCXX_PROFILE_DATA(__cost_factors)->
end(),
565 __cost_factor_writer(__file));
569 struct __cost_factor_setter
572 operator()(__cost_factor* __factor)
575 const char* __env_value = std::getenv(__factor->__env_var);
580 __env_t::iterator __it
581 = _GLIBCXX_PROFILE_DATA(__env).find(__factor->__env_var);
582 if (__it != _GLIBCXX_PROFILE_DATA(__env).
end())
583 __env_value = __it->second.c_str();
587 __factor->__value = std::atof(__env_value);
594 __cost_factor_vector* __factors =
new __cost_factor_vector;
595 _GLIBCXX_PROFILE_DATA(__cost_factors) = __factors;
596 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor));
597 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor));
598 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor));
599 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_shift_cost_factor));
600 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor));
601 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_resize_cost_factor));
602 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor));
603 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor));
604 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_find_cost_factor));
605 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor));
606 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor));
607 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor));
608 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_find_cost_factor));
609 __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor));
610 __for_each(__factors->begin(), __factors->end(), __cost_factor_setter());
614 __profcxx_init_unconditional()
620 __set_max_warn_count();
622 if (_GLIBCXX_PROFILE_DATA(_S_max_warn_count) == 0)
626 __set_max_stack_trace_depth();
629 __read_cost_factors();
630 __set_cost_factors();
631 __write_cost_factors();
633 __trace_vector_size_init();
634 __trace_hashtable_size_init();
635 __trace_hash_func_init();
636 __trace_vector_to_list_init();
637 __trace_list_to_slist_init();
638 __trace_list_to_vector_init();
639 __trace_map_to_unordered_map_init();
641 std::atexit(__report_and_free);
656 __profcxx_init_unconditional();
Hashtable size instrumentation trace producer.
size_type find_first_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character of string.
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.
void __report()
Final report method, registered with atexit.
basic_string substr(size_type __pos=0, size_type __n=npos) const
Get a substring.
Vector-to-list instrumentation producer.
Map-to-unordered_map instrumentation producer.
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters.
size_type length() const noexcept
Returns the number of characters in the string, not including any null-termination.
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"...
Representation of a warning.
size_type find(const _CharT *__s, size_type __pos, size_type __n) const
Find position of a C substring.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
Data structures to represent a single profiling event.
_GLIBCXX14_CONSTEXPR const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
bool __profcxx_init()
This function must be called by each instrumentation point.
Base class for all trace producers.
Algorithms used by the profile extension.
Controlling input for files.
Hashtable size instrumentation trace producer.
Hash function for summary trace using call stack as index.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
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.
size_type find_first_not_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character not in string.