libstdc++
profiler_list_to_vector.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Copyright (C) 2009-2015 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License along
00021 // with this library; see the file COPYING3.  If not see
00022 // <http://www.gnu.org/licenses/>.
00023 
00024 /** @file profile/impl/profiler_list_to_vector.h
00025  *  @brief diagnostics for list to vector.
00026  */
00027 
00028 // Written by Changhee Jung.
00029 
00030 #ifndef _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H
00031 #define _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H 1
00032 
00033 #include <sstream>
00034 
00035 #include "profile/impl/profiler.h"
00036 #include "profile/impl/profiler_node.h"
00037 #include "profile/impl/profiler_trace.h"
00038 
00039 namespace __gnu_profile
00040 {
00041   /** @brief A list-to-vector instrumentation line in the object table.  */
00042   class __list2vector_info
00043   : public __object_info_base
00044   {
00045   public:
00046     __list2vector_info(__stack_t __stack)
00047     : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0),
00048       _M_resize(0), _M_list_cost(0), _M_vector_cost(0),
00049       _M_max_size(0) { }
00050 
00051     void
00052     __merge(const __list2vector_info& __o)
00053     {
00054       __object_info_base::__merge(__o);
00055       _M_shift_count  += __o._M_shift_count;
00056       _M_iterate      += __o._M_iterate;
00057       _M_vector_cost  += __o._M_vector_cost;
00058       _M_list_cost    += __o._M_list_cost;
00059       _M_resize       += __o._M_resize;
00060       _M_max_size     = std::max( _M_max_size, __o._M_max_size);
00061     }
00062 
00063     void
00064     __write(FILE* __f) const
00065     {
00066       std::fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count,
00067                    _M_resize, _M_iterate, _M_vector_cost, _M_list_cost);
00068     }
00069 
00070     float
00071     __magnitude() const
00072     { return _M_list_cost - _M_vector_cost; }
00073   
00074     std::string
00075     __advice() const
00076     {
00077       std::stringstream __sstream;
00078       __sstream 
00079         << "change std::list to std::vector and its initial size from 0 to "
00080         << _M_max_size;
00081       return __sstream.str();
00082     }
00083 
00084     std::size_t
00085     __shift_count()
00086     { return _M_shift_count; }
00087   
00088     std::size_t
00089     __iterate()
00090     { return _M_iterate; }
00091   
00092     float
00093     __list_cost()
00094     { return _M_list_cost; }
00095   
00096     std::size_t
00097     __resize()
00098     { return _M_resize; }
00099   
00100     void
00101     __set_list_cost(float __lc)
00102     { _M_list_cost = __lc; }
00103     
00104     void
00105     __set_vector_cost(float __vc)
00106     { _M_vector_cost = __vc; }
00107     
00108     void
00109     __opr_insert(std::size_t __shift, std::size_t __size)
00110     {
00111       _M_shift_count += __shift;
00112       _M_max_size = std::max(_M_max_size, __size);
00113     }
00114 
00115     void
00116     __opr_iterate(int __num)
00117     { __gnu_cxx::__atomic_add(&_M_iterate, __num); }
00118 
00119     void
00120     __resize(std::size_t __from, std::size_t)
00121     { _M_resize += __from; }
00122 
00123   private:
00124     std::size_t _M_shift_count;
00125     mutable _Atomic_word _M_iterate;
00126     std::size_t _M_resize;
00127     float _M_list_cost;
00128     float _M_vector_cost;
00129     std::size_t _M_max_size;
00130   };
00131 
00132   class __list2vector_stack_info 
00133   : public __list2vector_info
00134   {
00135   public:
00136     __list2vector_stack_info(const __list2vector_info& __o) 
00137     : __list2vector_info(__o) {}
00138   };
00139 
00140   class __trace_list_to_vector
00141   : public __trace_base<__list2vector_info, __list2vector_stack_info> 
00142   {
00143   public:
00144     __trace_list_to_vector()
00145     : __trace_base<__list2vector_info, __list2vector_stack_info>()
00146     { __id = "list-to-vector"; }
00147 
00148     ~__trace_list_to_vector() { }
00149 
00150     // Call at destruction/clean to set container final size.
00151     void
00152     __destruct(__list2vector_info* __obj_info)
00153     {
00154       float __vc = __vector_cost(__obj_info->__shift_count(),
00155                                  __obj_info->__iterate());
00156       float __lc = __list_cost(__obj_info->__shift_count(),
00157                                __obj_info->__iterate());
00158       __obj_info->__set_vector_cost(__vc);
00159       __obj_info->__set_list_cost(__lc);
00160       __retire_object(__obj_info);
00161     }
00162 
00163     // Collect cost of operations.
00164     float
00165     __vector_cost(std::size_t __shift, std::size_t __iterate)
00166     {
00167       // The resulting vector will use a 'reserve' method.
00168       return (__shift
00169               * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value
00170               + __iterate
00171               * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value); 
00172     }
00173 
00174     float
00175     __list_cost(std::size_t __shift, std::size_t __iterate)
00176     {
00177       return (__shift
00178               * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value
00179               + __iterate
00180               * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value); 
00181     }
00182   };
00183 
00184 
00185   inline void
00186   __trace_list_to_vector_init()
00187   { _GLIBCXX_PROFILE_DATA(_S_list_to_vector) = new __trace_list_to_vector(); }
00188 
00189   inline void
00190   __trace_list_to_vector_free()
00191   { delete _GLIBCXX_PROFILE_DATA(_S_list_to_vector); }
00192 
00193   inline void
00194   __trace_list_to_vector_report(FILE* __f, __warning_vector_t& __warnings)
00195   { __trace_report(_GLIBCXX_PROFILE_DATA(_S_list_to_vector), __f, __warnings); }
00196 
00197   inline __list2vector_info*
00198   __trace_list_to_vector_construct()
00199   {
00200     if (!__profcxx_init())
00201       return 0;
00202 
00203     if (!__reentrance_guard::__get_in())
00204       return 0;
00205 
00206     __reentrance_guard __get_out;
00207     return _GLIBCXX_PROFILE_DATA(_S_list_to_vector)
00208       ->__add_object(__get_stack());
00209   }
00210 
00211   inline void
00212   __trace_list_to_vector_insert(__list2vector_info* __obj_info,
00213                                 std::size_t __shift, std::size_t __size)
00214   {
00215     if (!__obj_info)
00216       return;
00217 
00218     __obj_info->__opr_insert(__shift, __size);
00219   }
00220 
00221   inline void
00222   __trace_list_to_vector_iterate(__list2vector_info* __obj_info,
00223                                  int)
00224   {
00225     if (!__obj_info)
00226       return;
00227 
00228     // We only collect if an iteration took place no matter in what side.
00229     __obj_info->__opr_iterate(1);
00230   }
00231 
00232   inline void
00233   __trace_list_to_vector_invalid_operator(__list2vector_info* __obj_info)
00234   {
00235     if (!__obj_info)
00236       return;
00237 
00238     __obj_info->__set_invalid();
00239   }
00240 
00241   inline void
00242   __trace_list_to_vector_resize(__list2vector_info* __obj_info, 
00243                                 std::size_t __from, std::size_t __to)
00244   {
00245     if (!__obj_info)
00246       return;
00247 
00248     __obj_info->__resize(__from, __to);
00249   }
00250 
00251   inline void
00252   __trace_list_to_vector_destruct(__list2vector_info* __obj_info)
00253   {
00254     if (!__obj_info)
00255       return;
00256 
00257     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__destruct(__obj_info);
00258   }
00259 
00260 } // namespace __gnu_profile
00261 #endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H__ */