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_map_to_unordered_map.h 00025 * @brief Diagnostics for map to unordered_map. 00026 */ 00027 00028 // Written by Silvius Rus. 00029 00030 #ifndef _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H 00031 #define _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H 1 00032 00033 #include "profile/impl/profiler.h" 00034 #include "profile/impl/profiler_node.h" 00035 #include "profile/impl/profiler_trace.h" 00036 00037 namespace __gnu_profile 00038 { 00039 inline int 00040 __log2(std::size_t __size) 00041 { 00042 for (int __bit_count = sizeof(std::size_t) - 1; __bit_count >= 0; 00043 -- __bit_count) 00044 if ((2 << __bit_count) & __size) 00045 return __bit_count; 00046 return 0; 00047 } 00048 00049 inline float 00050 __map_insert_cost(std::size_t __size) 00051 { return (_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor).__value 00052 * static_cast<float>(__log2(__size))); } 00053 00054 inline float 00055 __map_erase_cost(std::size_t __size) 00056 { return (_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor).__value 00057 * static_cast<float>(__log2(__size))); } 00058 00059 inline float 00060 __map_find_cost(std::size_t __size) 00061 { return (_GLIBCXX_PROFILE_DATA(__map_find_cost_factor).__value 00062 * static_cast<float>(__log2(__size))); } 00063 00064 /** @brief A map-to-unordered_map instrumentation line in the 00065 object table. */ 00066 class __map2umap_info 00067 : public __object_info_base 00068 { 00069 public: 00070 __map2umap_info(__stack_t __stack) 00071 : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), 00072 _M_iterate(0), _M_umap_cost(0.0), _M_map_cost(0.0) 00073 { } 00074 00075 void 00076 __merge(const __map2umap_info& __o) 00077 { 00078 __object_info_base::__merge(__o); 00079 _M_insert += __o._M_insert; 00080 _M_erase += __o._M_erase; 00081 _M_find += __o._M_find; 00082 _M_iterate += __o._M_iterate; 00083 _M_umap_cost += __o._M_umap_cost; 00084 _M_map_cost += __o._M_map_cost; 00085 } 00086 00087 void 00088 __write(FILE* __f) const 00089 { 00090 std::fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f\n", 00091 _M_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, 00092 _M_umap_cost); 00093 } 00094 00095 float 00096 __magnitude() const 00097 { return _M_map_cost - _M_umap_cost; } 00098 00099 std::string 00100 __advice() const 00101 { return "prefer an unordered container"; } 00102 00103 void 00104 __record_insert(std::size_t __size, std::size_t __count) 00105 { 00106 ++_M_insert; 00107 if (__count) 00108 { 00109 _M_map_cost += __count * __map_insert_cost(__size); 00110 _M_umap_cost 00111 += (__count 00112 * _GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor).__value); 00113 } 00114 } 00115 00116 void 00117 __record_erase(std::size_t __size, std::size_t __count) 00118 { 00119 ++_M_erase; 00120 if (__count) 00121 { 00122 _M_map_cost += __count * __map_erase_cost(__size); 00123 _M_umap_cost 00124 += (__count 00125 * _GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor).__value); 00126 } 00127 } 00128 00129 void 00130 __record_find(std::size_t __size) 00131 { 00132 ++_M_find; 00133 _M_map_cost += __map_find_cost(__size); 00134 _M_umap_cost += _GLIBCXX_PROFILE_DATA(__umap_find_cost_factor).__value; 00135 } 00136 00137 void 00138 __record_iterate(int __count) 00139 { __gnu_cxx::__atomic_add(&_M_iterate, __count); } 00140 00141 void 00142 __set_iterate_costs() 00143 { 00144 _M_umap_cost 00145 += (_M_iterate 00146 * _GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor).__value); 00147 _M_map_cost 00148 += (_M_iterate 00149 * _GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor).__value); 00150 } 00151 00152 private: 00153 std::size_t _M_insert; 00154 std::size_t _M_erase; 00155 std::size_t _M_find; 00156 mutable _Atomic_word _M_iterate; 00157 float _M_umap_cost; 00158 float _M_map_cost; 00159 }; 00160 00161 00162 /** @brief A map-to-unordered_map instrumentation line in the 00163 stack table. */ 00164 class __map2umap_stack_info 00165 : public __map2umap_info 00166 { 00167 public: 00168 __map2umap_stack_info(const __map2umap_info& __o) 00169 : __map2umap_info(__o) { } 00170 }; 00171 00172 /** @brief Map-to-unordered_map instrumentation producer. */ 00173 class __trace_map2umap 00174 : public __trace_base<__map2umap_info, __map2umap_stack_info> 00175 { 00176 public: 00177 __trace_map2umap() 00178 : __trace_base<__map2umap_info, __map2umap_stack_info>() 00179 { __id = "ordered-to-unordered"; } 00180 00181 // Call at destruction/clean to set container final size. 00182 void 00183 __destruct(__map2umap_info* __obj_info) 00184 { 00185 __obj_info->__set_iterate_costs(); 00186 __retire_object(__obj_info); 00187 } 00188 }; 00189 00190 inline void 00191 __trace_map_to_unordered_map_init() 00192 { _GLIBCXX_PROFILE_DATA(_S_map2umap) = new __trace_map2umap(); } 00193 00194 inline void 00195 __trace_map_to_unordered_map_free() 00196 { delete _GLIBCXX_PROFILE_DATA(_S_map2umap); } 00197 00198 inline void 00199 __trace_map_to_unordered_map_report(FILE* __f, 00200 __warning_vector_t& __warnings) 00201 { __trace_report(_GLIBCXX_PROFILE_DATA(_S_map2umap), __f, __warnings); } 00202 00203 inline __map2umap_info* 00204 __trace_map_to_unordered_map_construct() 00205 { 00206 if (!__profcxx_init()) 00207 return 0; 00208 00209 if (!__reentrance_guard::__get_in()) 00210 return 0; 00211 00212 __reentrance_guard __get_out; 00213 return _GLIBCXX_PROFILE_DATA(_S_map2umap)->__add_object(__get_stack()); 00214 } 00215 00216 inline void 00217 __trace_map_to_unordered_map_insert(__map2umap_info* __info, 00218 std::size_t __size, std::size_t __count) 00219 { 00220 if (!__info) 00221 return; 00222 00223 __info->__record_insert(__size, __count); 00224 } 00225 00226 inline void 00227 __trace_map_to_unordered_map_erase(__map2umap_info* __info, 00228 std::size_t __size, std::size_t __count) 00229 { 00230 if (!__info) 00231 return; 00232 00233 __info->__record_erase(__size, __count); 00234 } 00235 00236 inline void 00237 __trace_map_to_unordered_map_find(__map2umap_info* __info, 00238 std::size_t __size) 00239 { 00240 if (!__info) 00241 return; 00242 00243 __info->__record_find(__size); 00244 } 00245 00246 inline void 00247 __trace_map_to_unordered_map_iterate(__map2umap_info* __info, 00248 int) 00249 { 00250 if (!__info) 00251 return; 00252 00253 // We only collect if an iteration took place no matter in what side. 00254 __info->__record_iterate(1); 00255 } 00256 00257 inline void 00258 __trace_map_to_unordered_map_invalidate(__map2umap_info* __info) 00259 { 00260 if (!__info) 00261 return; 00262 00263 __info->__set_invalid(); 00264 } 00265 00266 inline void 00267 __trace_map_to_unordered_map_destruct(__map2umap_info* __info) 00268 { 00269 if (!__info) 00270 return; 00271 00272 _GLIBCXX_PROFILE_DATA(_S_map2umap)->__destruct(__info); 00273 } 00274 } // namespace __gnu_profile 00275 #endif /* _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H */