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