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