Home | History | Annotate | Line # | Download | only in impl
      1 // -*- C++ -*-
      2 //
      3 // Copyright (C) 2009-2019 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(__stack_t __stack)
     47     : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0),
     48       _M_resize(0), _M_list_cost(0), _M_vector_cost(0),
     49       _M_max_size(0) { }
     50 
     51     void
     52     __merge(const __list2vector_info& __o)
     53     {
     54       __object_info_base::__merge(__o);
     55       _M_shift_count  += __o._M_shift_count;
     56       _M_iterate      += __o._M_iterate;
     57       _M_vector_cost  += __o._M_vector_cost;
     58       _M_list_cost    += __o._M_list_cost;
     59       _M_resize       += __o._M_resize;
     60       _M_max_size     = std::max( _M_max_size, __o._M_max_size);
     61     }
     62 
     63     void
     64     __write(FILE* __f) const
     65     {
     66       std::fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count,
     67 		   _M_resize, _M_iterate, _M_vector_cost, _M_list_cost);
     68     }
     69 
     70     float
     71     __magnitude() const
     72     { return _M_list_cost - _M_vector_cost; }
     73 
     74     std::string
     75     __advice() const
     76     {
     77       std::stringstream __sstream;
     78       __sstream
     79 	<< "change std::list to std::vector and its initial size from 0 to "
     80 	<< _M_max_size;
     81       return __sstream.str();
     82     }
     83 
     84     std::size_t
     85     __shift_count()
     86     { return _M_shift_count; }
     87 
     88     std::size_t
     89     __iterate()
     90     { return _M_iterate; }
     91 
     92     float
     93     __list_cost()
     94     { return _M_list_cost; }
     95 
     96     std::size_t
     97     __resize()
     98     { return _M_resize; }
     99 
    100     void
    101     __set_list_cost(float __lc)
    102     { _M_list_cost = __lc; }
    103 
    104     void
    105     __set_vector_cost(float __vc)
    106     { _M_vector_cost = __vc; }
    107 
    108     void
    109     __opr_insert(std::size_t __shift, std::size_t __size)
    110     {
    111       _M_shift_count += __shift;
    112       _M_max_size = std::max(_M_max_size, __size);
    113     }
    114 
    115     void
    116     __opr_iterate(int __num)
    117     { __gnu_cxx::__atomic_add(&_M_iterate, __num); }
    118 
    119     void
    120     __resize(std::size_t __from, std::size_t)
    121     { _M_resize += __from; }
    122 
    123   private:
    124     std::size_t _M_shift_count;
    125     mutable _Atomic_word _M_iterate;
    126     std::size_t _M_resize;
    127     float _M_list_cost;
    128     float _M_vector_cost;
    129     std::size_t _M_max_size;
    130   };
    131 
    132   class __list2vector_stack_info
    133   : public __list2vector_info
    134   {
    135   public:
    136     __list2vector_stack_info(const __list2vector_info& __o)
    137     : __list2vector_info(__o) {}
    138   };
    139 
    140   class __trace_list_to_vector
    141   : public __trace_base<__list2vector_info, __list2vector_stack_info>
    142   {
    143   public:
    144     __trace_list_to_vector()
    145     : __trace_base<__list2vector_info, __list2vector_stack_info>()
    146     { __id = "list-to-vector"; }
    147 
    148     ~__trace_list_to_vector() { }
    149 
    150     // Call at destruction/clean to set container final size.
    151     void
    152     __destruct(__list2vector_info* __obj_info)
    153     {
    154       float __vc = __vector_cost(__obj_info->__shift_count(),
    155 				 __obj_info->__iterate());
    156       float __lc = __list_cost(__obj_info->__shift_count(),
    157 			       __obj_info->__iterate());
    158       __obj_info->__set_vector_cost(__vc);
    159       __obj_info->__set_list_cost(__lc);
    160       __retire_object(__obj_info);
    161     }
    162 
    163     // Collect cost of operations.
    164     float
    165     __vector_cost(std::size_t __shift, std::size_t __iterate)
    166     {
    167       // The resulting vector will use a 'reserve' method.
    168       return (__shift
    169 	      * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value
    170 	      + __iterate
    171 	      * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value);
    172     }
    173 
    174     float
    175     __list_cost(std::size_t __shift, std::size_t __iterate)
    176     {
    177       return (__shift
    178 	      * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value
    179 	      + __iterate
    180 	      * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value);
    181     }
    182   };
    183 
    184 
    185   inline void
    186   __trace_list_to_vector_init()
    187   { _GLIBCXX_PROFILE_DATA(_S_list_to_vector) = new __trace_list_to_vector(); }
    188 
    189   inline void
    190   __trace_list_to_vector_free()
    191   { delete _GLIBCXX_PROFILE_DATA(_S_list_to_vector); }
    192 
    193   inline void
    194   __trace_list_to_vector_report(FILE* __f, __warning_vector_t& __warnings)
    195   { __trace_report(_GLIBCXX_PROFILE_DATA(_S_list_to_vector), __f, __warnings); }
    196 
    197   inline __list2vector_info*
    198   __trace_list_to_vector_construct()
    199   {
    200     if (!__profcxx_init())
    201       return 0;
    202 
    203     if (!__reentrance_guard::__get_in())
    204       return 0;
    205 
    206     __reentrance_guard __get_out;
    207     return _GLIBCXX_PROFILE_DATA(_S_list_to_vector)
    208       ->__add_object(__get_stack());
    209   }
    210 
    211   inline void
    212   __trace_list_to_vector_insert(__list2vector_info* __obj_info,
    213 				std::size_t __shift, std::size_t __size)
    214   {
    215     if (!__obj_info)
    216       return;
    217 
    218     __obj_info->__opr_insert(__shift, __size);
    219   }
    220 
    221   inline void
    222   __trace_list_to_vector_iterate(__list2vector_info* __obj_info,
    223 				 int)
    224   {
    225     if (!__obj_info)
    226       return;
    227 
    228     // We only collect if an iteration took place no matter in what side.
    229     __obj_info->__opr_iterate(1);
    230   }
    231 
    232   inline void
    233   __trace_list_to_vector_invalid_operator(__list2vector_info* __obj_info)
    234   {
    235     if (!__obj_info)
    236       return;
    237 
    238     __obj_info->__set_invalid();
    239   }
    240 
    241   inline void
    242   __trace_list_to_vector_resize(__list2vector_info* __obj_info,
    243 				std::size_t __from, std::size_t __to)
    244   {
    245     if (!__obj_info)
    246       return;
    247 
    248     __obj_info->__resize(__from, __to);
    249   }
    250 
    251   inline void
    252   __trace_list_to_vector_destruct(__list2vector_info* __obj_info)
    253   {
    254     if (!__obj_info)
    255       return;
    256 
    257     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__destruct(__obj_info);
    258   }
    259 
    260 } // namespace __gnu_profile
    261 #endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H__ */
    262