Home | History | Annotate | Download | only in impl
      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