libstdc++
profiler_trace.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License along
21 // with this library; see the file COPYING3. If not see
22 // <http://www.gnu.org/licenses/>.
23 
24 /** @file profile/impl/profiler_trace.h
25  * @brief Data structures to represent profiling traces.
26  */
27 
28 // Written by Lixia Liu and Silvius Rus.
29 
30 #ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H
31 #define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1
32 
33 #include <cstdio> // fopen, fclose, fprintf, FILE
34 #include <cerrno>
35 #include <cstdlib> // atof, atoi, strtol, getenv, atexit, abort
36 
37 #if __cplusplus >= 201103L
38 #include <unordered_map>
39 #define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_C::unordered_map
40 #else
41 #include <tr1/unordered_map>
42 #define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
43 #endif
44 
45 #include <ext/concurrence.h>
46 #include <fstream>
47 #include <string>
48 #include <utility>
49 #include <vector>
50 
54 
55 namespace __gnu_profile
56 {
57  /** @brief Internal environment. Values can be set one of two ways:
58  1. In config file "var = value". The default config file path is
59  libstdcxx-profile.conf.
60  2. By setting process environment variables. For instance, in a Bash
61  shell you can set the unit cost of iterating through a map like this:
62  export __map_iterate_cost_factor=5.0.
63  If a value is set both in the input file and through an environment
64  variable, the environment value takes precedence. */
65  typedef _GLIBCXX_IMPL_UNORDERED_MAP<std::string, std::string> __env_t;
66 
67  _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__env_t, __env);
68 
69  /** @brief Master lock. */
70  _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__gnu_cxx::__mutex, __global_mutex);
71 
72  /** @brief Representation of a warning. */
74  {
75  float __magnitude;
76  __stack_t __context;
77  const char* __warning_id;
78  std::string __warning_message;
79 
81  : __magnitude(0.0), __context(0), __warning_id(0) { }
82 
83  __warning_data(float __m, __stack_t __c, const char* __id,
84  const std::string& __msg)
85  : __magnitude(__m), __context(__c), __warning_id(__id),
86  __warning_message(__msg) { }
87 
88  bool
89  operator<(const __warning_data& __other) const
90  { return __magnitude < __other.__magnitude; }
91  };
92 
93  typedef std::_GLIBCXX_STD_C::vector<__warning_data> __warning_vector_t;
94 
95  // Defined in profiler_<diagnostic name>.h.
96  class __trace_hash_func;
98  class __trace_map2umap;
99  class __trace_vector_size;
101  class __trace_list_to_slist;
102  class __trace_list_to_vector;
103  void __trace_vector_size_init();
104  void __trace_hashtable_size_init();
105  void __trace_hash_func_init();
106  void __trace_vector_to_list_init();
107  void __trace_list_to_slist_init();
108  void __trace_list_to_vector_init();
109  void __trace_map_to_unordered_map_init();
110  void __trace_vector_size_report(FILE*, __warning_vector_t&);
111  void __trace_hashtable_size_report(FILE*, __warning_vector_t&);
112  void __trace_hash_func_report(FILE*, __warning_vector_t&);
113  void __trace_vector_to_list_report(FILE*, __warning_vector_t&);
114  void __trace_list_to_slist_report(FILE*, __warning_vector_t&);
115  void __trace_list_to_vector_report(FILE*, __warning_vector_t&);
116  void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&);
117  void __trace_vector_size_free();
118  void __trace_hashtable_size_free();
119  void __trace_hash_func_free();
120  void __trace_vector_to_list_free();
121  void __trace_list_to_slist_free();
122  void __trace_list_to_vector_free();
123  void __trace_map_to_unordered_map_free();
124 
125  struct __cost_factor
126  {
127  const char* __env_var;
128  float __value;
129  };
130 
131  typedef std::_GLIBCXX_STD_C::vector<__cost_factor*> __cost_factor_vector;
132 
133  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, 0);
134  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, 0);
135  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, 0);
136  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, 0);
137  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, 0);
138  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, 0);
139  _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, 0);
140 
141  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_shift_cost_factor,
142  {"__vector_shift_cost_factor", 1.0});
143  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_iterate_cost_factor,
144  {"__vector_iterate_cost_factor", 1.0});
145  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_resize_cost_factor,
146  {"__vector_resize_cost_factor", 1.0});
147  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_shift_cost_factor,
148  {"__list_shift_cost_factor", 0.0});
149  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_iterate_cost_factor,
150  {"__list_iterate_cost_factor", 10.0});
151  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_resize_cost_factor,
152  {"__list_resize_cost_factor", 0.0});
153  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_insert_cost_factor,
154  {"__map_insert_cost_factor", 1.5});
155  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_erase_cost_factor,
156  {"__map_erase_cost_factor", 1.5});
157  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_find_cost_factor,
158  {"__map_find_cost_factor", 1});
159  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_iterate_cost_factor,
160  {"__map_iterate_cost_factor", 2.3});
161  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_insert_cost_factor,
162  {"__umap_insert_cost_factor", 12.0});
163  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_erase_cost_factor,
164  {"__umap_erase_cost_factor", 12.0});
165  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_find_cost_factor,
166  {"__umap_find_cost_factor", 10.0});
167  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_iterate_cost_factor,
168  {"__umap_iterate_cost_factor", 1.7});
169  _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor_vector*, __cost_factors, 0);
170 
171  _GLIBCXX_PROFILE_DEFINE_DATA(const char*, _S_trace_file_name,
172  _GLIBCXX_PROFILE_TRACE_PATH_ROOT);
173  _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_warn_count,
174  _GLIBCXX_PROFILE_MAX_WARN_COUNT);
175  _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_stack_depth,
176  _GLIBCXX_PROFILE_MAX_STACK_DEPTH);
177  _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_mem,
178  _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC);
179 
180  inline std::size_t
181  __stack_max_depth()
182  { return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); }
183 
184  inline std::size_t
185  __max_mem()
186  { return _GLIBCXX_PROFILE_DATA(_S_max_mem); }
187 
188  /** @brief Base class for all trace producers. */
189  template<typename __object_info, typename __stack_info>
191  {
192  public:
193  // Do not pick the initial size too large, as we don't know which
194  // diagnostics are more active.
195  __trace_base()
196  : __objects_byte_size(0), __stack_table(10000),
197  __stack_table_byte_size(0), __id(0) { }
198 
199  ~__trace_base()
200  {
201  for (typename __stack_table_t::iterator __it
202  = __stack_table.begin(); __it != __stack_table.end(); ++__it)
203  delete __it->first;
204  }
205 
206  __object_info* __add_object(__stack_t __stack);
207  void __retire_object(__object_info* __info);
208  void __write(FILE* __f);
209  void __collect_warnings(__warning_vector_t& __warnings);
210  void __free();
211 
212  private:
213  __gnu_cxx::__mutex __trace_mutex;
214  typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info,
215  __stack_hash,
216  __stack_hash> __stack_table_t;
217  std::size_t __objects_byte_size;
218  __stack_table_t __stack_table;
219  std::size_t __stack_table_byte_size;
220 
221  protected:
222  const char* __id;
223  };
224 
225  template<typename __object_info, typename __stack_info>
226  __object_info*
228  __add_object(__stack_t __stack)
229  {
230  // If we have no backtrace information no need to collect data.
231  if (!__stack)
232  return 0;
233 
234  __gnu_cxx::__scoped_lock __lock(this->__trace_mutex);
235 
236  if (__max_mem() != 0 && __objects_byte_size >= __max_mem())
237  {
238  delete __stack;
239  return 0;
240  }
241 
242  __object_info* __ret = new(std::nothrow) __object_info(__stack);
243  if (!__ret)
244  {
245  delete __stack;
246  return 0;
247  }
248 
249  __objects_byte_size += sizeof(__object_info);
250  return __ret;
251  }
252 
253  template<typename __object_info, typename __stack_info>
254  void
256  __retire_object(__object_info* __obj_info)
257  {
258  if (!__obj_info)
259  return;
260 
261  __gnu_cxx::__scoped_lock __lock(this->__trace_mutex);
262 
263  const __object_info& __info = *__obj_info;
264  __stack_t __stack = __info.__stack();
265  typename __stack_table_t::iterator __stack_it
266  = __stack_table.find(__stack);
267 
268  if (__stack_it == __stack_table.end())
269  {
270  // First occurrence of this call context.
271  if (__max_mem() == 0 || __stack_table_byte_size < __max_mem())
272  {
273  __stack_table_byte_size
274  += (sizeof(__instruction_address_t) * __size(__stack)
275  + sizeof(__stack) + sizeof(__stack_info));
276  __stack_table.insert(make_pair(__stack,
277  __stack_info(__info)));
278  }
279  else
280  delete __stack;
281  }
282  else
283  {
284  // Merge object info into info summary for this call context.
285  __stack_it->second.__merge(__info);
286  delete __stack;
287  }
288 
289  delete __obj_info;
290  __objects_byte_size -= sizeof(__object_info);
291  }
292 
293  template<typename __object_info, typename __stack_info>
294  void
296  __write(FILE* __f)
297  {
298  for (typename __stack_table_t::iterator __it
299  = __stack_table.begin(); __it != __stack_table.end(); ++__it)
300  if (__it->second.__is_valid())
301  {
302  std::fprintf(__f, __id);
303  std::fprintf(__f, "|");
304  __gnu_profile::__write(__f, __it->first);
305  std::fprintf(__f, "|");
306  __it->second.__write(__f);
307  }
308  }
309 
310  template<typename __object_info, typename __stack_info>
311  void
313  __collect_warnings(__warning_vector_t& __warnings)
314  {
315  for (typename __stack_table_t::iterator __it
316  = __stack_table.begin(); __it != __stack_table.end(); ++__it)
317  __warnings.push_back(__warning_data(__it->second.__magnitude(),
318  __it->first, __id,
319  __it->second.__advice()));
320  }
321 
322  template<typename __object_info, typename __stack_info>
323  inline void
324  __trace_report(__trace_base<__object_info, __stack_info>* __cont,
325  FILE* __f, __warning_vector_t& __warnings)
326  {
327  if (__cont)
328  {
329  __cont->__collect_warnings(__warnings);
330  __cont->__write(__f);
331  }
332  }
333 
334  inline std::size_t
335  __env_to_size_t(const char* __env_var, std::size_t __default_value)
336  {
337  char* __env_value = std::getenv(__env_var);
338  if (__env_value)
339  {
340  errno = 0;
341  long __converted_value = std::strtol(__env_value, 0, 10);
342  if (errno || __converted_value < 0)
343  {
344  std::fprintf(stderr,
345  "Bad value for environment variable '%s'.\n",
346  __env_var);
347  std::abort();
348  }
349  else
350  return static_cast<std::size_t>(__converted_value);
351  }
352  else
353  return __default_value;
354  }
355 
356  inline void
357  __set_max_stack_trace_depth()
358  {
359  _GLIBCXX_PROFILE_DATA(_S_max_stack_depth)
360  = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR,
361  _GLIBCXX_PROFILE_DATA(_S_max_stack_depth));
362  }
363 
364  inline void
365  __set_max_mem()
366  {
367  _GLIBCXX_PROFILE_DATA(_S_max_mem)
368  = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR,
369  _GLIBCXX_PROFILE_DATA(_S_max_mem));
370  }
371 
372  inline int
373  __log_magnitude(float __f)
374  {
375  const float __log_base = 10.0;
376  int __result = 0;
377  int __sign = 1;
378 
379  if (__f < 0)
380  {
381  __f = -__f;
382  __sign = -1;
383  }
384 
385  while (__f > __log_base)
386  {
387  ++__result;
388  __f /= 10.0;
389  }
390  return __sign * __result;
391  }
392 
393  inline FILE*
394  __open_output_file(const char* __extension)
395  {
396  // The path is made of _S_trace_file_name + "." + extension.
397  std::size_t __root_len
398  = __builtin_strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
399  std::size_t __ext_len = __builtin_strlen(__extension);
400  char* __file_name = new char[__root_len + 1 + __ext_len + 1];
401  __builtin_memcpy(__file_name,
402  _GLIBCXX_PROFILE_DATA(_S_trace_file_name),
403  __root_len);
404  *(__file_name + __root_len) = '.';
405  __builtin_memcpy(__file_name + __root_len + 1,
406  __extension, __ext_len + 1);
407 
408  FILE* __out_file = std::fopen(__file_name, "w");
409  if (!__out_file)
410  {
411  std::fprintf(stderr, "Could not open trace file '%s'.\n",
412  __file_name);
413  std::abort();
414  }
415 
416  delete[] __file_name;
417  return __out_file;
418  }
419 
420  struct __warn
421  {
422  FILE* __file;
423 
424  __warn(FILE* __f)
425  { __file = __f; }
426 
427  void
428  operator()(const __warning_data& __info)
429  {
430  std::fprintf(__file, __info.__warning_id);
431  std::fprintf(__file, ": improvement = %d",
432  __log_magnitude(__info.__magnitude));
433  std::fprintf(__file, ": call stack = ");
434  __gnu_profile::__write(__file, __info.__context);
435  std::fprintf(__file, ": advice = %s\n",
436  __info.__warning_message.c_str());
437  }
438  };
439 
440  /** @brief Final report method, registered with @b atexit.
441  *
442  * This can also be called directly by user code, including signal handlers.
443  * It is protected against deadlocks by the reentrance guard in profiler.h.
444  * However, when called from a signal handler that triggers while within
445  * __gnu_profile (under the guarded zone), no output will be produced.
446  */
447  inline void
449  {
450  __gnu_cxx::__scoped_lock __lock(_GLIBCXX_PROFILE_DATA(__global_mutex));
451 
452  __warning_vector_t __warnings, __top_warnings;
453 
454  FILE* __raw_file = __open_output_file("raw");
455  __trace_vector_size_report(__raw_file, __warnings);
456  __trace_hashtable_size_report(__raw_file, __warnings);
457  __trace_hash_func_report(__raw_file, __warnings);
458  __trace_vector_to_list_report(__raw_file, __warnings);
459  __trace_list_to_slist_report(__raw_file, __warnings);
460  __trace_list_to_vector_report(__raw_file, __warnings);
461  __trace_map_to_unordered_map_report(__raw_file, __warnings);
462  std::fclose(__raw_file);
463 
464  // Sort data by magnitude, keeping just top N.
465  std::size_t __cutoff = std::min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count),
466  __warnings.size());
467  __top_n(__warnings, __top_warnings, __cutoff);
468 
469  FILE* __warn_file = __open_output_file("txt");
470  __for_each(__top_warnings.begin(), __top_warnings.end(),
471  __warn(__warn_file));
472  std::fclose(__warn_file);
473  }
474 
475  inline void
476  __report_and_free()
477  {
478  __report();
479 
480  __trace_map_to_unordered_map_free();
481  __trace_list_to_vector_free();
482  __trace_list_to_slist_free();
483  __trace_vector_to_list_free();
484  __trace_hash_func_free();
485  __trace_hashtable_size_free();
486  __trace_vector_size_free();
487  delete _GLIBCXX_PROFILE_DATA(__cost_factors);
488  }
489 
490  inline void
491  __set_trace_path()
492  {
493  char* __env_trace_file_name = std::getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
494 
495  if (__env_trace_file_name)
496  _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name;
497 
498  // Make sure early that we can create the trace file.
499  std::fclose(__open_output_file("txt"));
500  }
501 
502  inline void
503  __set_max_warn_count()
504  {
505  char* __env_max_warn_count_str
506  = std::getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
507 
508  if (__env_max_warn_count_str)
509  _GLIBCXX_PROFILE_DATA(_S_max_warn_count)
510  = static_cast<std::size_t>(std::atoi(__env_max_warn_count_str));
511  }
512 
513  inline void
514  __read_cost_factors()
515  {
516  std::string __conf_file_name(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
517  __conf_file_name += ".conf";
518 
519  std::ifstream __conf_file(__conf_file_name.c_str());
520 
521  if (__conf_file.is_open())
522  {
523  std::string __line;
524 
525  while (std::getline(__conf_file, __line))
526  {
527  std::string::size_type __i = __line.find_first_not_of(" \t\n\v");
528 
529  if (__line.length() <= 0 || __line[__i] == '#')
530  // Skip empty lines or comments.
531  continue;
532  }
533 
534  // Trim.
535  __line.erase(__remove(__line.begin(), __line.end(), ' '),
536  __line.end());
537  std::string::size_type __pos = __line.find("=");
538  std::string __factor_name = __line.substr(0, __pos);
539  std::string::size_type __end = __line.find_first_of(";\n");
540  std::string __factor_value = __line.substr(__pos + 1, __end - __pos);
541 
542  _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value;
543  }
544  }
545 
546  struct __cost_factor_writer
547  {
548  FILE* __file;
549 
550  __cost_factor_writer(FILE* __f)
551  : __file(__f) { }
552 
553  void
554  operator() (const __cost_factor* __factor)
555  { std::fprintf(__file, "%s = %f\n", __factor->__env_var,
556  __factor->__value); }
557  };
558 
559  inline void
560  __write_cost_factors()
561  {
562  FILE* __file = __open_output_file("conf.out");
563  __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(),
564  _GLIBCXX_PROFILE_DATA(__cost_factors)->end(),
565  __cost_factor_writer(__file));
566  std::fclose(__file);
567  }
568 
569  struct __cost_factor_setter
570  {
571  void
572  operator()(__cost_factor* __factor)
573  {
574  // Look it up in the process environment first.
575  const char* __env_value = std::getenv(__factor->__env_var);
576 
577  if (!__env_value)
578  {
579  // Look it up in the config file.
580  __env_t::iterator __it
581  = _GLIBCXX_PROFILE_DATA(__env).find(__factor->__env_var);
582  if (__it != _GLIBCXX_PROFILE_DATA(__env).end())
583  __env_value = __it->second.c_str();
584  }
585 
586  if (__env_value)
587  __factor->__value = std::atof(__env_value);
588  }
589  };
590 
591  inline void
592  __set_cost_factors()
593  {
594  __cost_factor_vector* __factors = new __cost_factor_vector;
595  _GLIBCXX_PROFILE_DATA(__cost_factors) = __factors;
596  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor));
597  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor));
598  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor));
599  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_shift_cost_factor));
600  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor));
601  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__list_resize_cost_factor));
602  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor));
603  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor));
604  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_find_cost_factor));
605  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor));
606  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor));
607  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor));
608  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_find_cost_factor));
609  __factors->push_back(&_GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor));
610  __for_each(__factors->begin(), __factors->end(), __cost_factor_setter());
611  }
612 
613  inline void
614  __profcxx_init_unconditional()
615  {
616  __gnu_cxx::__scoped_lock __lock(_GLIBCXX_PROFILE_DATA(__global_mutex));
617 
618  if (__is_invalid())
619  {
620  __set_max_warn_count();
621 
622  if (_GLIBCXX_PROFILE_DATA(_S_max_warn_count) == 0)
623  __turn_off();
624  else
625  {
626  __set_max_stack_trace_depth();
627  __set_max_mem();
628  __set_trace_path();
629  __read_cost_factors();
630  __set_cost_factors();
631  __write_cost_factors();
632 
633  __trace_vector_size_init();
634  __trace_hashtable_size_init();
635  __trace_hash_func_init();
636  __trace_vector_to_list_init();
637  __trace_list_to_slist_init();
638  __trace_list_to_vector_init();
639  __trace_map_to_unordered_map_init();
640 
641  std::atexit(__report_and_free);
642 
643  __turn_on();
644  }
645  }
646  }
647 
648  /** @brief This function must be called by each instrumentation point.
649  *
650  * The common path is inlined fully.
651  */
652  inline bool
654  {
655  if (__is_invalid())
656  __profcxx_init_unconditional();
657 
658  return __is_on();
659  }
660 
661 } // namespace __gnu_profile
662 
663 #endif /* _GLIBCXX_PROFILE_PROFILER_TRACE_H */
Vector-to-list instrumentation producer.
Scoped lock idiom.
Definition: concurrence.h:231
Map-to-unordered_map instrumentation producer.
GNU profile code for public use.
Representation of a warning.
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.
Definition: stl_pair.h:276
void __report()
Final report method, registered with atexit.
Global profiler state.
Controlling input for files.
Definition: fstream:455
Hashtable size instrumentation trace producer.
Hashtable size instrumentation trace producer.
Base class for all trace producers.
size_type find(const _CharT *__s, size_type __pos, size_type __n) const
Find position of a C substring.
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"...
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
Data structures to represent a single profiling event.
_GLIBCXX14_CONSTEXPR const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:195
bool __profcxx_init()
This function must be called by each instrumentation point.
size_type find_first_not_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character not in string.
Hash function for summary trace using call stack as index.
Definition: profiler_node.h:93
Algorithms used by the profile extension.
Hash performance instrumentation producer.
size_type find_first_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character of string.
const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
basic_string substr(size_type __pos=0, size_type __n=npos) const
Get a substring.
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.
size_type length() const noexcept
Returns the number of characters in the string, not including any null-termination.