libstdc++
|
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 */