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_list_to_vector.h 32 * @brief diagnostics for list to vector. 33 */ 34 35 // Written by Changhee Jung. 36 37 #ifndef _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H 38 #define _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H 1 39 40 #include <sstream> 41 42 #include "profile/impl/profiler.h" 43 #include "profile/impl/profiler_node.h" 44 #include "profile/impl/profiler_trace.h" 45 46 namespace __gnu_profile 47 { 48 /** @brief A list-to-vector instrumentation line in the object table. */ 49 class __list2vector_info 50 : public __object_info_base 51 { 52 public: 53 __list2vector_info() 54 : _M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0), 55 _M_vector_cost(0), _M_valid(true), _M_max_size(0) { } 56 57 __list2vector_info(__stack_t __stack) 58 : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0), 59 _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true), 60 _M_max_size(0) { } 61 62 virtual ~__list2vector_info() { } 63 64 __list2vector_info(const __list2vector_info& __o) 65 : __object_info_base(__o), _M_shift_count(__o._M_shift_count), 66 _M_iterate(__o._M_iterate), _M_resize(__o._M_resize), 67 _M_list_cost(__o._M_list_cost), _M_vector_cost(__o._M_vector_cost), 68 _M_valid(__o._M_valid), _M_max_size(__o._M_max_size) { } 69 70 void 71 __merge(const __list2vector_info& __o) 72 { 73 _M_shift_count += __o._M_shift_count; 74 _M_iterate += __o._M_iterate; 75 _M_vector_cost += __o._M_vector_cost; 76 _M_list_cost += __o._M_list_cost; 77 _M_valid &= __o._M_valid; 78 _M_resize += __o._M_resize; 79 _M_max_size = std::max( _M_max_size, __o._M_max_size); 80 } 81 82 void 83 __write(FILE* __f) const 84 { 85 std::fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count, 86 _M_resize, _M_iterate, _M_vector_cost, _M_list_cost); 87 } 88 89 float 90 __magnitude() const 91 { return _M_list_cost - _M_vector_cost; } 92 93 std::string 94 __advice() const 95 { 96 std::stringstream __sstream; 97 __sstream 98 << "change std::list to std::vector and its initial size from 0 to " 99 << _M_max_size; 100 return __sstream.str(); 101 } 102 103 std::size_t 104 __shift_count() 105 { return _M_shift_count; } 106 107 std::size_t 108 __iterate() 109 { return _M_iterate; } 110 111 float 112 __list_cost() 113 { return _M_list_cost; } 114 115 std::size_t 116 __resize() 117 { return _M_resize; } 118 119 void 120 __set_list_cost(float __lc) 121 { _M_list_cost = __lc; } 122 123 void 124 __set_vector_cost(float __vc) 125 { _M_vector_cost = __vc; } 126 127 bool 128 __is_valid() 129 { return _M_valid; } 130 131 void 132 __set_invalid() 133 { _M_valid = false; } 134 135 void 136 __opr_insert(std::size_t __shift, std::size_t __size) 137 { 138 _M_shift_count += __shift; 139 _M_max_size = std::max(_M_max_size, __size); 140 } 141 142 void 143 __opr_iterate(std::size_t __num) 144 { _M_iterate += __num;} 145 146 void 147 __resize(std::size_t __from, std::size_t) 148 { _M_resize += __from; } 149 150 private: 151 std::size_t _M_shift_count; 152 std::size_t _M_iterate; 153 std::size_t _M_resize; 154 float _M_list_cost; 155 float _M_vector_cost; 156 bool _M_valid; 157 std::size_t _M_max_size; 158 }; 159 160 class __list2vector_stack_info 161 : public __list2vector_info 162 { 163 public: 164 __list2vector_stack_info(const __list2vector_info& __o) 165 : __list2vector_info(__o) {} 166 }; 167 168 class __trace_list_to_vector 169 : public __trace_base<__list2vector_info, __list2vector_stack_info> 170 { 171 public: 172 __trace_list_to_vector() 173 : __trace_base<__list2vector_info, __list2vector_stack_info>() 174 { __id = "list-to-vector"; } 175 176 ~__trace_list_to_vector() { } 177 178 // Insert a new node at construct with object, callstack and initial size. 179 void 180 __insert(__object_t __obj, __stack_t __stack) 181 { __add_object(__obj, __list2vector_info(__stack)); } 182 183 // Call at destruction/clean to set container final size. 184 void 185 __destruct(const void* __obj) 186 { 187 if (!__is_on()) 188 return; 189 190 __list2vector_info* __res = __get_object_info(__obj); 191 if (!__res) 192 return; 193 194 float __vc = __vector_cost(__res->__shift_count(), __res->__iterate()); 195 float __lc = __list_cost(__res->__shift_count(), __res->__iterate()); 196 __res->__set_vector_cost(__vc); 197 __res->__set_list_cost(__lc); 198 __retire_object(__obj); 199 } 200 201 // Find the node in the live map. 202 __list2vector_info* __find(const void* __obj); 203 204 // Collect cost of operations. 205 void 206 __opr_insert(const void* __obj, std::size_t __shift, std::size_t __size) 207 { 208 __list2vector_info* __res = __get_object_info(__obj); 209 if (__res) 210 __res->__opr_insert(__shift, __size); 211 } 212 213 void 214 __opr_iterate(const void* __obj, std::size_t __num) 215 { 216 __list2vector_info* __res = __get_object_info(__obj); 217 if (__res) 218 __res->__opr_iterate(__num); 219 } 220 221 void 222 __invalid_operator(const void* __obj) 223 { 224 __list2vector_info* __res = __get_object_info(__obj); 225 if (__res) 226 __res->__set_invalid(); 227 } 228 229 void 230 __resize(const void* __obj, std::size_t __from, std::size_t __to) 231 { 232 __list2vector_info* __res = __get_object_info(__obj); 233 if (__res) 234 __res->__resize(__from, __to); 235 } 236 237 float 238 __vector_cost(std::size_t __shift, std::size_t __iterate) 239 { 240 // The resulting vector will use a 'reserve' method. 241 return (__shift 242 * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value 243 + __iterate 244 * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value); 245 } 246 247 float 248 __list_cost(std::size_t __shift, std::size_t __iterate) 249 { 250 return (__shift 251 * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value 252 + __iterate 253 * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value); 254 } 255 }; 256 257 258 inline void 259 __trace_list_to_vector_init() 260 { _GLIBCXX_PROFILE_DATA(_S_list_to_vector) = new __trace_list_to_vector(); } 261 262 inline void 263 __trace_list_to_vector_report(FILE* __f, __warning_vector_t& __warnings) 264 { 265 if (_GLIBCXX_PROFILE_DATA(_S_list_to_vector)) 266 { 267 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)-> 268 __collect_warnings(__warnings); 269 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__write(__f); 270 } 271 } 272 273 inline void 274 __trace_list_to_vector_construct(const void* __obj) 275 { 276 if (!__profcxx_init()) 277 return; 278 279 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__insert(__obj, __get_stack()); 280 } 281 282 inline void 283 __trace_list_to_vector_destruct(const void* __obj) 284 { 285 if (!__profcxx_init()) 286 return; 287 288 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__destruct(__obj); 289 } 290 291 inline void 292 __trace_list_to_vector_insert(const void* __obj, 293 std::size_t __shift, std::size_t __size) 294 { 295 if (!__profcxx_init()) 296 return; 297 298 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__opr_insert(__obj, __shift, 299 __size); 300 } 301 302 inline void 303 __trace_list_to_vector_iterate(const void* __obj, std::size_t __num = 1) 304 { 305 if (!__profcxx_init()) 306 return; 307 308 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__opr_iterate(__obj, __num); 309 } 310 311 inline void 312 __trace_list_to_vector_invalid_operator(const void* __obj) 313 { 314 if (!__profcxx_init()) 315 return; 316 317 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__invalid_operator(__obj); 318 } 319 320 inline void 321 __trace_list_to_vector_resize(const void* __obj, 322 std::size_t __from, std::size_t __to) 323 { 324 if (!__profcxx_init()) 325 return; 326 327 _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__resize(__obj, __from, __to); 328 } 329 330 } // namespace __gnu_profile 331 #endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H__ */ 332