libstdc++
profiler_trace.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Copyright (C) 2009-2015 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License along
00021 // with this library; see the file COPYING3.  If not see
00022 // <http://www.gnu.org/licenses/>.
00023 
00024 /** @file profile/impl/profiler_trace.h
00025  *  @brief Data structures to represent profiling traces.
00026  */
00027 
00028 // Written by Lixia Liu and Silvius Rus.
00029 
00030 #ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H
00031 #define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1
00032 
00033 #include <cstdio>  // fopen, fclose, fprintf, FILE
00034 #include <cerrno>
00035 #include <cstdlib> // atof, atoi, strtol, getenv, atexit, abort
00036 
00037 #if __cplusplus >= 201103L
00038 #include <unordered_map>
00039 #define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_C::unordered_map
00040 #else
00041 #include <tr1/unordered_map>
00042 #define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
00043 #endif
00044 
00045 #include <ext/concurrence.h>
00046 #include <fstream>
00047 #include <string>
00048 #include <utility>
00049 #include <vector>
00050 
00051 #include "profile/impl/profiler_algos.h"
00052 #include "profile/impl/profiler_state.h"
00053 #include "profile/impl/profiler_node.h"
00054 
00055 namespace __gnu_profile
00056 {
00057   /** @brief Internal environment.  Values can be set one of two ways:
00058       1. In config file "var = value".  The default config file path is 
00059          libstdcxx-profile.conf.
00060       2. By setting process environment variables.  For instance, in a Bash
00061          shell you can set the unit cost of iterating through a map like this:
00062          export __map_iterate_cost_factor=5.0.
00063          If a value is set both in the input file and through an environment
00064          variable, the environment value takes precedence.  */
00065   typedef _GLIBCXX_IMPL_UNORDERED_MAP<std::string, std::string> __env_t;
00066 
00067   _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__env_t, __env);
00068 
00069   /** @brief Master lock.  */
00070   _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__gnu_cxx::__mutex, __global_mutex);
00071 
00072   /** @brief Representation of a warning.  */
00073   struct __warning_data
00074   {
00075     float __magnitude;
00076     __stack_t __context;
00077     const char* __warning_id;
00078     std::string __warning_message;
00079 
00080     __warning_data()
00081     : __magnitude(0.0), __context(0), __warning_id(0) { }
00082 
00083     __warning_data(float __m, __stack_t __c, const char* __id, 
00084                    const std::string& __msg)
00085     : __magnitude(__m), __context(__c), __warning_id(__id), 
00086       __warning_message(__msg) { }
00087 
00088     bool
00089     operator<(const __warning_data& __other) const
00090     { return __magnitude < __other.__magnitude; }
00091   };
00092 
00093   typedef std::_GLIBCXX_STD_C::vector<__warning_data> __warning_vector_t;
00094 
00095   // Defined in profiler_<diagnostic name>.h.
00096   class __trace_hash_func;
00097   class __trace_hashtable_size;
00098   class __trace_map2umap;
00099   class __trace_vector_size;
00100   class __trace_vector_to_list;
00101   class __trace_list_to_slist; 
00102   class __trace_list_to_vector; 
00103   void __trace_vector_size_init();
00104   void __trace_hashtable_size_init();
00105   void __trace_hash_func_init();
00106   void __trace_vector_to_list_init();
00107   void __trace_list_to_slist_init();  
00108   void __trace_list_to_vector_init();  
00109   void __trace_map_to_unordered_map_init();
00110   void __trace_vector_size_report(FILE*, __warning_vector_t&);
00111   void __trace_hashtable_size_report(FILE*, __warning_vector_t&);
00112   void __trace_hash_func_report(FILE*, __warning_vector_t&);
00113   void __trace_vector_to_list_report(FILE*, __warning_vector_t&);
00114   void __trace_list_to_slist_report(FILE*, __warning_vector_t&); 
00115   void __trace_list_to_vector_report(FILE*, __warning_vector_t&);
00116   void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&);
00117   void __trace_vector_size_free();
00118   void __trace_hashtable_size_free();
00119   void __trace_hash_func_free();
00120   void __trace_vector_to_list_free();
00121   void __trace_list_to_slist_free();  
00122   void __trace_list_to_vector_free();  
00123   void __trace_map_to_unordered_map_free();
00124 
00125   struct __cost_factor
00126   {
00127     const char* __env_var;
00128     float __value;
00129   };
00130 
00131   typedef std::_GLIBCXX_STD_C::vector<__cost_factor*> __cost_factor_vector;
00132 
00133   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, 0);
00134   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, 0);
00135   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, 0);
00136   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, 0);
00137   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, 0);
00138   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, 0); 
00139   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, 0);
00140 
00141   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_shift_cost_factor, 
00142                                {"__vector_shift_cost_factor", 1.0});
00143   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_iterate_cost_factor,
00144                                {"__vector_iterate_cost_factor", 1.0});
00145   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_resize_cost_factor,
00146                                {"__vector_resize_cost_factor", 1.0}); 
00147   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_shift_cost_factor,
00148                                {"__list_shift_cost_factor", 0.0});
00149   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_iterate_cost_factor,
00150                                {"__list_iterate_cost_factor", 10.0}); 
00151   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_resize_cost_factor,
00152                                {"__list_resize_cost_factor", 0.0}); 
00153   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_insert_cost_factor,
00154                                {"__map_insert_cost_factor", 1.5});
00155   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_erase_cost_factor,
00156                                {"__map_erase_cost_factor", 1.5});
00157   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_find_cost_factor,
00158                                {"__map_find_cost_factor", 1});
00159   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_iterate_cost_factor,
00160                                {"__map_iterate_cost_factor", 2.3});
00161   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_insert_cost_factor,
00162                                {"__umap_insert_cost_factor", 12.0});
00163   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_erase_cost_factor,
00164                                {"__umap_erase_cost_factor", 12.0});
00165   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_find_cost_factor,
00166                                {"__umap_find_cost_factor", 10.0});
00167   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_iterate_cost_factor,
00168                                {"__umap_iterate_cost_factor", 1.7});
00169   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor_vector*, __cost_factors, 0);
00170 
00171   _GLIBCXX_PROFILE_DEFINE_DATA(const char*, _S_trace_file_name,
00172                                _GLIBCXX_PROFILE_TRACE_PATH_ROOT);
00173   _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_warn_count,
00174                                _GLIBCXX_PROFILE_MAX_WARN_COUNT);
00175   _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_stack_depth,
00176                                _GLIBCXX_PROFILE_MAX_STACK_DEPTH);
00177   _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_mem,
00178                                _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC);
00179 
00180   inline std::size_t
00181   __stack_max_depth()
00182   { return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); }
00183 
00184   inline std::size_t
00185   __max_mem()
00186   { return _GLIBCXX_PROFILE_DATA(_S_max_mem); }
00187 
00188   /** @brief Base class for all trace producers.  */
00189   template<typename __object_info, typename __stack_info>
00190     class __trace_base
00191     {
00192     public:
00193       // Do not pick the initial size too large, as we don't know which
00194       // diagnostics are more active.
00195       __trace_base()
00196       : __objects_byte_size(0), __stack_table(10000),
00197         __stack_table_byte_size(0), __id(0) { }
00198 
00199       ~__trace_base()
00200       {
00201         for (typename __stack_table_t::iterator __it
00202                = __stack_table.begin(); __it != __stack_table.end(); ++__it)
00203           delete __it->first;
00204       }
00205 
00206       __object_info* __add_object(__stack_t __stack);
00207       void __retire_object(__object_info* __info);
00208       void __write(FILE* __f);
00209       void __collect_warnings(__warning_vector_t& __warnings);
00210       void __free();
00211 
00212     private:
00213       __gnu_cxx::__mutex __trace_mutex;
00214       typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info,
00215                                           __stack_hash, 
00216                                           __stack_hash> __stack_table_t;
00217       std::size_t __objects_byte_size;
00218       __stack_table_t __stack_table;
00219       std::size_t __stack_table_byte_size;
00220 
00221     protected:
00222       const char* __id;
00223     };
00224 
00225   template<typename __object_info, typename __stack_info>
00226     __object_info*
00227     __trace_base<__object_info, __stack_info>::
00228     __add_object(__stack_t __stack)
00229     {
00230       // If we have no backtrace information no need to collect data.
00231       if (!__stack)
00232         return 0;
00233 
00234       __gnu_cxx::__scoped_lock __lock(this->__trace_mutex);
00235 
00236       if (__max_mem() != 0 && __objects_byte_size >= __max_mem())
00237         {
00238           delete __stack;
00239           return 0;
00240         }
00241 
00242       __object_info* __ret = new(std::nothrow) __object_info(__stack);
00243       if (!__ret)
00244         {
00245           delete __stack;
00246           return 0;
00247         }
00248 
00249       __objects_byte_size += sizeof(__object_info);
00250       return __ret;
00251     }
00252 
00253   template<typename __object_info, typename __stack_info>
00254     void
00255     __trace_base<__object_info, __stack_info>::
00256     __retire_object(__object_info* __obj_info)
00257     {
00258       if (!__obj_info)
00259         return;
00260 
00261       __gnu_cxx::__scoped_lock __lock(this->__trace_mutex);
00262 
00263       const __object_info& __info = *__obj_info;
00264       __stack_t __stack = __info.__stack();
00265       typename __stack_table_t::iterator __stack_it
00266         = __stack_table.find(__stack);
00267     
00268       if (__stack_it == __stack_table.end())
00269         {
00270           // First occurrence of this call context.
00271           if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) 
00272             {
00273               __stack_table_byte_size 
00274                 += (sizeof(__instruction_address_t) * __size(__stack)
00275                     + sizeof(__stack) + sizeof(__stack_info));
00276               __stack_table.insert(make_pair(__stack,
00277                                              __stack_info(__info)));
00278             }
00279           else
00280             delete __stack;
00281         }
00282       else
00283         {
00284           // Merge object info into info summary for this call context.
00285           __stack_it->second.__merge(__info);
00286           delete __stack;
00287         }
00288 
00289       delete __obj_info;
00290       __objects_byte_size -= sizeof(__object_info);
00291     }
00292 
00293   template<typename __object_info, typename __stack_info>
00294     void
00295     __trace_base<__object_info, __stack_info>::
00296     __write(FILE* __f)
00297     {
00298       for (typename __stack_table_t::iterator __it
00299              = __stack_table.begin(); __it != __stack_table.end(); ++__it)
00300         if (__it->second.__is_valid())
00301           {
00302             std::fprintf(__f, __id);
00303             std::fprintf(__f, "|");
00304             __gnu_profile::__write(__f, __it->first);
00305             std::fprintf(__f, "|");
00306             __it->second.__write(__f);
00307           }
00308     }
00309 
00310   template<typename __object_info, typename __stack_info>
00311     void
00312     __trace_base<__object_info, __stack_info>::
00313     __collect_warnings(__warning_vector_t& __warnings)
00314     {
00315       for (typename __stack_table_t::iterator __it
00316              = __stack_table.begin(); __it != __stack_table.end(); ++__it)
00317         __warnings.push_back(__warning_data(__it->second.__magnitude(),
00318                                             __it->first, __id,
00319                                             __it->second.__advice()));
00320     }
00321 
00322   template<typename __object_info, typename __stack_info>
00323     inline void
00324     __trace_report(__trace_base<__object_info, __stack_info>* __cont,
00325                    FILE* __f, __warning_vector_t& __warnings)
00326     {
00327       if (__cont)
00328         {
00329           __cont->__collect_warnings(__warnings);
00330           __cont->__write(__f);
00331         }
00332     }
00333   
00334   inline std::size_t
00335   __env_to_size_t(const char* __env_var, std::size_t __default_value)
00336   {
00337     char* __env_value = std::getenv(__env_var);
00338     if (__env_value)
00339       {
00340         errno = 0;
00341         long __converted_value = std::strtol(__env_value, 0, 10);
00342         if (errno || __converted_value < 0)
00343           {
00344             std::fprintf(stderr,
00345                          "Bad value for environment variable '%s'.\n",
00346                          __env_var);
00347             std::abort();
00348           }
00349         else
00350           return static_cast<std::size_t>(__converted_value);
00351       }
00352     else
00353       return __default_value;
00354   }
00355 
00356   inline void
00357   __set_max_stack_trace_depth()
00358   {
00359     _GLIBCXX_PROFILE_DATA(_S_max_stack_depth)
00360       = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR,
00361                         _GLIBCXX_PROFILE_DATA(_S_max_stack_depth));
00362   }
00363 
00364   inline void
00365   __set_max_mem()
00366   {
00367     _GLIBCXX_PROFILE_DATA(_S_max_mem) 
00368       = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR,
00369                         _GLIBCXX_PROFILE_DATA(_S_max_mem));
00370   }
00371 
00372   inline int
00373   __log_magnitude(float __f)
00374   {
00375     const float __log_base = 10.0;
00376     int __result = 0;
00377     int __sign = 1;
00378 
00379     if (__f < 0) 
00380       {
00381         __f = -__f;
00382         __sign = -1;
00383       }
00384 
00385     while (__f > __log_base) 
00386       {
00387         ++__result;
00388         __f /= 10.0;
00389       }
00390     return __sign * __result;
00391   }
00392 
00393   inline FILE* 
00394   __open_output_file(const char* __extension)
00395   {
00396     // The path is made of _S_trace_file_name + "." + extension.
00397     std::size_t __root_len 
00398       = __builtin_strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
00399     std::size_t __ext_len = __builtin_strlen(__extension);
00400     char* __file_name = new char[__root_len + 1 + __ext_len + 1];
00401     __builtin_memcpy(__file_name,
00402                      _GLIBCXX_PROFILE_DATA(_S_trace_file_name),
00403                      __root_len);
00404     *(__file_name + __root_len) = '.';
00405     __builtin_memcpy(__file_name + __root_len + 1,
00406                      __extension, __ext_len + 1);
00407 
00408     FILE* __out_file = std::fopen(__file_name, "w");
00409     if (!__out_file)
00410       {
00411         std::fprintf(stderr, "Could not open trace file '%s'.\n",
00412                      __file_name);
00413         std::abort();
00414       }
00415 
00416     delete[] __file_name;
00417     return __out_file;
00418   }
00419 
00420   struct __warn
00421   {
00422     FILE* __file;
00423 
00424     __warn(FILE* __f)
00425     { __file = __f; }
00426 
00427     void
00428     operator()(const __warning_data& __info)
00429     {
00430       std::fprintf(__file,  __info.__warning_id);
00431       std::fprintf(__file, ": improvement = %d",
00432                    __log_magnitude(__info.__magnitude));
00433       std::fprintf(__file, ": call stack = ");
00434       __gnu_profile::__write(__file, __info.__context);
00435       std::fprintf(__file, ": advice = %s\n",
00436                    __info.__warning_message.c_str());
00437     }
00438   };
00439 
00440   /** @brief Final report method, registered with @b atexit.
00441    *
00442    * This can also be called directly by user code, including signal handlers.
00443    * It is protected against deadlocks by the reentrance guard in profiler.h.
00444    * However, when called from a signal handler that triggers while within
00445    * __gnu_profile (under the guarded zone), no output will be produced.
00446    */
00447   inline void
00448   __report()
00449   {
00450     __gnu_cxx::__scoped_lock __lock(_GLIBCXX_PROFILE_DATA(__global_mutex));
00451 
00452     __warning_vector_t __warnings, __top_warnings;
00453 
00454     FILE* __raw_file = __open_output_file("raw");
00455     __trace_vector_size_report(__raw_file, __warnings);
00456     __trace_hashtable_size_report(__raw_file, __warnings);
00457     __trace_hash_func_report(__raw_file, __warnings);
00458     __trace_vector_to_list_report(__raw_file, __warnings);
00459     __trace_list_to_slist_report(__raw_file, __warnings);
00460     __trace_list_to_vector_report(__raw_file, __warnings);
00461     __trace_map_to_unordered_map_report(__raw_file, __warnings);
00462     std::fclose(__raw_file);
00463 
00464     // Sort data by magnitude, keeping just top N.
00465     std::size_t __cutoff = std::min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count),
00466                                     __warnings.size());
00467     __top_n(__warnings, __top_warnings, __cutoff);
00468 
00469     FILE* __warn_file = __open_output_file("txt");
00470     __for_each(__top_warnings.begin(), __top_warnings.end(),
00471                __warn(__warn_file));
00472     std::fclose(__warn_file);
00473   }
00474 
00475   inline void
00476   __report_and_free()
00477   {
00478     __report();
00479 
00480     __trace_map_to_unordered_map_free();
00481     __trace_list_to_vector_free();
00482     __trace_list_to_slist_free(); 
00483     __trace_vector_to_list_free();
00484     __trace_hash_func_free();
00485     __trace_hashtable_size_free();
00486     __trace_vector_size_free();
00487     delete _GLIBCXX_PROFILE_DATA(__cost_factors);
00488   }
00489 
00490   inline void
00491   __set_trace_path()
00492   {
00493     char* __env_trace_file_name = std::getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
00494 
00495     if (__env_trace_file_name)
00496       _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name;
00497 
00498     // Make sure early that we can create the trace file.
00499     std::fclose(__open_output_file("txt"));
00500   }
00501 
00502   inline void
00503   __set_max_warn_count()
00504   {
00505     char* __env_max_warn_count_str
00506       = std::getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
00507 
00508     if (__env_max_warn_count_str)
00509       _GLIBCXX_PROFILE_DATA(_S_max_warn_count)
00510         = static_cast<std::size_t>(std::atoi(__env_max_warn_count_str));
00511   }
00512 
00513   inline void
00514   __read_cost_factors()
00515   {
00516     std::string __conf_file_name(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
00517     __conf_file_name += ".conf";
00518 
00519     std::ifstream __conf_file(__conf_file_name.c_str());
00520 
00521     if (__conf_file.is_open())
00522       {
00523         std::string __line;
00524 
00525         while (std::getline(__conf_file, __line))
00526           {
00527             std::string::size_type __i = __line.find_first_not_of(" \t\n\v");
00528 
00529             if (__line.length() <= 0 || __line[__i] == '#')
00530               // Skip empty lines or comments.
00531               continue;
00532           }
00533 
00534         // Trim.
00535         __line.erase(__remove(__line.begin(), __line.end(), ' '),
00536                      __line.end());
00537         std::string::size_type __pos = __line.find("=");
00538         std::string __factor_name = __line.substr(0, __pos);
00539         std::string::size_type __end = __line.find_first_of(";\n");
00540         std::string __factor_value = __line.substr(__pos + 1, __end - __pos);
00541 
00542         _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value;
00543       }
00544   }
00545 
00546   struct __cost_factor_writer
00547   {
00548     FILE* __file;
00549 
00550     __cost_factor_writer(FILE* __f)
00551     : __file(__f) { }
00552 
00553     void
00554     operator() (const __cost_factor* __factor)
00555     { std::fprintf(__file, "%s = %f\n", __factor->__env_var,
00556                    __factor->__value); }
00557   };
00558 
00559   inline void
00560   __write_cost_factors()
00561   {
00562     FILE* __file = __open_output_file("conf.out");
00563     __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(),
00564                _GLIBCXX_PROFILE_DATA(__cost_factors)->end(),
00565                __cost_factor_writer(__file));
00566     std::fclose(__file);
00567   }
00568 
00569   struct __cost_factor_setter
00570   {
00571     void
00572     operator()(__cost_factor* __factor)
00573     {
00574       // Look it up in the process environment first.
00575       const char* __env_value = std::getenv(__factor->__env_var);
00576 
00577       if (!__env_value)
00578         {
00579           // Look it up in the config file.
00580           __env_t::iterator __it
00581             = _GLIBCXX_PROFILE_DATA(__env).find(__factor->__env_var);
00582           if (__it != _GLIBCXX_PROFILE_DATA(__env).end())
00583             __env_value = __it->second.c_str();
00584         }
00585 
00586       if (__env_value)
00587         __factor->__value = std::atof(__env_value);
00588     }
00589   };
00590 
00591   inline void
00592   __set_cost_factors()
00593   {
00594     __cost_factor_vector* __factors = new __cost_factor_vector;
00595     _GLIBCXX_PROFILE_DATA(__cost_factors) = __factors;
00596     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor));
00597     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor));
00598     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor));
00599     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_shift_cost_factor));
00600     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor));
00601     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_resize_cost_factor));
00602     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor));
00603     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor));
00604     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_find_cost_factor));
00605     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor));
00606     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor));
00607     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor));
00608     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_find_cost_factor));
00609     __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor));
00610     __for_each(__factors->begin(), __factors->end(), __cost_factor_setter());
00611   }
00612 
00613   inline void
00614   __profcxx_init_unconditional()
00615   {
00616     __gnu_cxx::__scoped_lock __lock(_GLIBCXX_PROFILE_DATA(__global_mutex));
00617 
00618     if (__is_invalid())
00619       {
00620         __set_max_warn_count();
00621 
00622         if (_GLIBCXX_PROFILE_DATA(_S_max_warn_count) == 0)
00623           __turn_off();
00624         else
00625           {
00626             __set_max_stack_trace_depth();
00627             __set_max_mem();
00628             __set_trace_path();
00629             __read_cost_factors(); 
00630             __set_cost_factors();
00631             __write_cost_factors();
00632 
00633             __trace_vector_size_init();
00634             __trace_hashtable_size_init();
00635             __trace_hash_func_init();
00636             __trace_vector_to_list_init();
00637             __trace_list_to_slist_init(); 
00638             __trace_list_to_vector_init();
00639             __trace_map_to_unordered_map_init();
00640 
00641             std::atexit(__report_and_free);
00642 
00643             __turn_on();
00644           }
00645       }
00646   }
00647 
00648   /** @brief This function must be called by each instrumentation point.
00649    *
00650    * The common path is inlined fully.
00651    */
00652   inline bool
00653   __profcxx_init()
00654   {
00655     if (__is_invalid())
00656       __profcxx_init_unconditional();
00657 
00658     return __is_on();
00659   }
00660 
00661 } // namespace __gnu_profile
00662 
00663 #endif /* _GLIBCXX_PROFILE_PROFILER_TRACE_H */