1 // -*- C++ -*- 2 // 3 // Copyright (C) 2009, 2010 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 terms 7 // of the GNU General Public License as published by the Free Software 8 // Foundation; either version 2, or (at your option) any later 9 // version. 10 11 // This library is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // General Public License for more details. 15 16 // You should have received a copy of the GNU General Public License 17 // along with this library; see the file COPYING. If not, write to 18 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston, 19 // MA 02111-1307, USA. 20 21 // As a special exception, you may use this file as part of a free 22 // software library without restriction. Specifically, if other files 23 // instantiate templates or use macros or inline functions from this 24 // file, or you compile this file and link it with other files to 25 // produce an executable, this file does not by itself cause the 26 // resulting executable to be covered by the GNU General Public 27 // License. This exception does not however invalidate any other 28 // reasons why the executable file might be covered by the GNU General 29 // Public License. 30 31 /** @file profile/impl/profiler_map_to_unordered_map.h 32 * @brief Diagnostics for map to unordered_map. 33 */ 34 35 // Written by Silvius Rus. 36 37 #ifndef _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H 38 #define _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H 1 39 40 #include "profile/impl/profiler.h" 41 #include "profile/impl/profiler_node.h" 42 #include "profile/impl/profiler_trace.h" 43 44 namespace __gnu_profile 45 { 46 inline int 47 __log2(std::size_t __size) 48 { 49 for (int __bit_count = sizeof(std::size_t) - 1; __bit_count >= 0; 50 -- __bit_count) 51 if ((2 << __bit_count) & __size) 52 return __bit_count; 53 return 0; 54 } 55 56 inline float 57 __map_insert_cost(std::size_t __size) 58 { return (_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor).__value 59 * static_cast<float>(__log2(__size))); } 60 61 inline float 62 __map_erase_cost(std::size_t __size) 63 { return (_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor).__value 64 * static_cast<float>(__log2(__size))); } 65 66 inline float 67 __map_find_cost(std::size_t __size) 68 { return (_GLIBCXX_PROFILE_DATA(__map_find_cost_factor).__value 69 * static_cast<float>(__log2(__size))); } 70 71 /** @brief A map-to-unordered_map instrumentation line in the 72 object table. */ 73 class __map2umap_info 74 : public __object_info_base 75 { 76 public: 77 __map2umap_info() 78 : _M_insert(0), _M_erase(0), _M_find(0), _M_iterate(0), 79 _M_umap_cost(0.0), _M_map_cost(0.0), _M_valid(true) { } 80 81 __map2umap_info(__stack_t __stack) 82 : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), 83 _M_iterate(0), _M_umap_cost(0.0), _M_map_cost(0.0), _M_valid(true) { } 84 85 virtual ~__map2umap_info() { } 86 87 __map2umap_info(const __map2umap_info& __o) 88 : __object_info_base(__o), _M_insert(__o._M_insert), 89 _M_erase(__o._M_erase), _M_find(__o._M_find), 90 _M_iterate(__o._M_iterate), _M_umap_cost(__o._M_umap_cost), 91 _M_map_cost(__o._M_map_cost), _M_valid(__o._M_valid) { } 92 93 void 94 __merge(const __map2umap_info& __o) 95 { 96 _M_insert += __o._M_insert; 97 _M_erase += __o._M_erase; 98 _M_find += __o._M_find; 99 _M_umap_cost += __o._M_umap_cost; 100 _M_map_cost += __o._M_map_cost; 101 _M_valid &= __o._M_valid; 102 } 103 104 void 105 __write(FILE* __f) const 106 { 107 std::fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f %s\n", 108 _M_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, 109 _M_umap_cost, _M_valid ? "valid" : "invalid"); 110 } 111 112 float 113 __magnitude() const 114 { return _M_map_cost - _M_umap_cost; } 115 116 std::string 117 __advice() const 118 { return "change std::map to std::unordered_map"; } 119 120 void 121 __record_insert(std::size_t __size, std::size_t __count) 122 { 123 _M_insert += __count; 124 _M_map_cost += __count * __map_insert_cost(__size); 125 _M_umap_cost 126 += (__count 127 * _GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor).__value); 128 } 129 130 void 131 __record_erase(std::size_t __size, std::size_t __count) 132 { 133 _M_erase += __count; 134 _M_map_cost += __count * __map_erase_cost(__size); 135 _M_umap_cost 136 += (__count 137 * _GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor).__value); 138 } 139 140 void 141 __record_find(std::size_t __size) 142 { 143 _M_find += 1; 144 _M_map_cost += __map_find_cost(__size); 145 _M_umap_cost += _GLIBCXX_PROFILE_DATA(__umap_find_cost_factor).__value; 146 } 147 148 void 149 __record_iterate(std::size_t __count) 150 { 151 _M_iterate += __count; 152 _M_map_cost 153 += (__count 154 * _GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor).__value); 155 _M_umap_cost 156 += (__count 157 * _GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor).__value); 158 } 159 160 void 161 __record_invalidate() 162 { _M_valid = false; } 163 164 private: 165 std::size_t _M_insert; 166 std::size_t _M_erase; 167 std::size_t _M_find; 168 std::size_t _M_iterate; 169 float _M_umap_cost; 170 float _M_map_cost; 171 bool _M_valid; 172 }; 173 174 175 /** @brief A map-to-unordered_map instrumentation line in the 176 stack table. */ 177 class __map2umap_stack_info 178 : public __map2umap_info 179 { 180 public: 181 __map2umap_stack_info(const __map2umap_info& __o) 182 : __map2umap_info(__o) { } 183 }; 184 185 /** @brief Map-to-unordered_map instrumentation producer. */ 186 class __trace_map2umap 187 : public __trace_base<__map2umap_info, __map2umap_stack_info> 188 { 189 public: 190 __trace_map2umap() 191 : __trace_base<__map2umap_info, __map2umap_stack_info>() 192 { __id = "map-to-unordered-map"; } 193 }; 194 195 inline void 196 __trace_map_to_unordered_map_init() 197 { _GLIBCXX_PROFILE_DATA(_S_map2umap) = new __trace_map2umap(); } 198 199 inline void 200 __trace_map_to_unordered_map_report(FILE* __f, 201 __warning_vector_t& __warnings) 202 { 203 if (_GLIBCXX_PROFILE_DATA(_S_map2umap)) 204 { 205 _GLIBCXX_PROFILE_DATA(_S_map2umap)->__collect_warnings(__warnings); 206 _GLIBCXX_PROFILE_DATA(_S_map2umap)->__write(__f); 207 } 208 } 209 210 inline void 211 __trace_map_to_unordered_map_construct(const void* __obj) 212 { 213 if (!__profcxx_init()) 214 return; 215 216 _GLIBCXX_PROFILE_DATA(_S_map2umap)-> 217 __add_object(__obj, __map2umap_info(__get_stack())); 218 } 219 220 inline void 221 __trace_map_to_unordered_map_destruct(const void* __obj) 222 { 223 if (!__profcxx_init()) 224 return; 225 226 _GLIBCXX_PROFILE_DATA(_S_map2umap)->__retire_object(__obj); 227 } 228 229 inline void 230 __trace_map_to_unordered_map_insert(const void* __obj, 231 std::size_t __size, std::size_t __count) 232 { 233 if (!__profcxx_init()) 234 return; 235 236 __map2umap_info* __info 237 = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); 238 239 if (__info) 240 __info->__record_insert(__size, __count); 241 } 242 243 inline void 244 __trace_map_to_unordered_map_erase(const void* __obj, 245 std::size_t __size, std::size_t __count) 246 { 247 if (!__profcxx_init()) 248 return; 249 250 __map2umap_info* __info 251 = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); 252 253 if (__info) 254 __info->__record_erase(__size, __count); 255 } 256 257 inline void 258 __trace_map_to_unordered_map_find(const void* __obj, std::size_t __size) 259 { 260 if (!__profcxx_init()) 261 return; 262 263 __map2umap_info* __info 264 = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); 265 266 if (__info) 267 __info->__record_find(__size); 268 } 269 270 inline void 271 __trace_map_to_unordered_map_iterate(const void* __obj, std::size_t __count) 272 { 273 if (!__profcxx_init()) 274 return; 275 276 __map2umap_info* __info 277 = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); 278 279 if (__info) 280 __info->__record_iterate(__count); 281 } 282 283 inline void 284 __trace_map_to_unordered_map_invalidate(const void* __obj) 285 { 286 if (!__profcxx_init()) 287 return; 288 289 __map2umap_info* __info 290 = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); 291 292 if (__info) 293 __info->__record_invalidate(); 294 } 295 296 } // namespace __gnu_profile 297 #endif /* _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H */ 298