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();
 
size_type find(const _CharT *__s, size_type __pos, size_type __n) const 
Find position of a C substring. 
bool __profcxx_init()
This function must be called by each instrumentation point. 
Base class for all trace producers. 
Hash function for summary trace using call stack as index. 
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_string substr(size_type __pos=0, size_type __n=npos) const 
Get a substring. 
Data structures to represent a single profiling event. 
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters. 
Hashtable size instrumentation trace producer. 
auto end(_Container &__cont) -> decltype(__cont.end())
Return an iterator pointing to one past the last element of the container. 
Vector-to-list instrumentation producer. 
auto begin(_Container &__cont) -> decltype(__cont.begin())
Return an iterator pointing to the first element of the container. 
size_type length() const noexcept
Returns the number of characters in the string, not including any null-termination. 
const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does. 
Hash performance instrumentation 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. 
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. 
void __report(void)
Final report method, registered with atexit. 
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. 
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"...
GNU profile code for public use. 
Algorithms used by the profile extension. 
Map-to-unordered_map instrumentation producer. 
Representation of a warning.