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 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] ==
'#')
535 __line.erase(__remove(__line.begin(), __line.end(),
' '),
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();
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
GNU profile code for public use.
Representation of a warning.
Algorithms used by the profile extension.
Map-to-unordered_map instrumentation producer.
_GLIBCXX_END_NAMESPACE_CXX11 typedef basic_string< char > string
A string of char.
Controlling input for files.
Base class for all trace producers.
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"...
bool __profcxx_init()
This function must be called by each instrumentation point.
basic_string substr(size_type __pos=0, size_type __n=npos) const
Get a substring.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
Vector-to-list instrumentation producer.
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.
Hashtable size instrumentation trace producer.
_GLIBCXX14_CONSTEXPR const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Hash function for summary trace using call stack as index.
void __report()
Final report method, registered with atexit.
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.
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.
Hash performance instrumentation producer.
Data structures to represent a single profiling event.
size_type find_first_not_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character not in string.