libstdc++
profiler_list_to_vector.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Copyright (C) 2009, 2010 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 terms
00007 // of the GNU General Public License as published by the Free Software
00008 // Foundation; either version 2, or (at your option) any later
00009 // version.
00010 
00011 // This library is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License
00017 // along with this library; see the file COPYING.  If not, write to
00018 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00019 // MA 02111-1307, USA.
00020 
00021 // As a special exception, you may use this file as part of a free
00022 // software library without restriction.  Specifically, if other files
00023 // instantiate templates or use macros or inline functions from this
00024 // file, or you compile this file and link it with other files to
00025 // produce an executable, this file does not by itself cause the
00026 // resulting executable to be covered by the GNU General Public
00027 // License.  This exception does not however invalidate any other
00028 // reasons why the executable file might be covered by the GNU General
00029 // Public License.
00030 
00031 /** @file profile/impl/profiler_list_to_vector.h
00032  *  @brief diagnostics for list to vector.
00033  */
00034 
00035 // Written by Changhee Jung.
00036 
00037 #ifndef _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H
00038 #define _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H 1
00039 
00040 #include <sstream>
00041 
00042 #include "profile/impl/profiler.h"
00043 #include "profile/impl/profiler_node.h"
00044 #include "profile/impl/profiler_trace.h"
00045 
00046 namespace __gnu_profile
00047 {
00048   /** @brief A list-to-vector instrumentation line in the object table.  */
00049   class __list2vector_info
00050   : public __object_info_base
00051   {
00052   public:
00053     __list2vector_info()
00054     : _M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0),
00055       _M_vector_cost(0), _M_valid(true), _M_max_size(0) { }
00056 
00057     __list2vector_info(__stack_t __stack)
00058     : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0),
00059       _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true),
00060       _M_max_size(0) { }
00061 
00062     virtual ~__list2vector_info() { }
00063 
00064     __list2vector_info(const __list2vector_info& __o)
00065     : __object_info_base(__o), _M_shift_count(__o._M_shift_count),
00066       _M_iterate(__o._M_iterate), _M_resize(__o._M_resize),
00067       _M_list_cost(__o._M_list_cost), _M_vector_cost(__o._M_vector_cost),
00068       _M_valid(__o._M_valid), _M_max_size(__o._M_max_size) { }
00069 
00070     void
00071     __merge(const __list2vector_info& __o)
00072     {
00073       _M_shift_count  += __o._M_shift_count;
00074       _M_iterate      += __o._M_iterate;
00075       _M_vector_cost  += __o._M_vector_cost;
00076       _M_list_cost    += __o._M_list_cost;
00077       _M_valid        &= __o._M_valid;
00078       _M_resize       += __o._M_resize;
00079       _M_max_size     = std::max( _M_max_size, __o._M_max_size);
00080     }
00081 
00082     void
00083     __write(FILE* __f) const
00084     {
00085       std::fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count,
00086            _M_resize, _M_iterate, _M_vector_cost, _M_list_cost);
00087     }
00088 
00089     float
00090     __magnitude() const
00091     { return _M_list_cost - _M_vector_cost; }
00092   
00093     std::string
00094     __advice() const
00095     {
00096       std::stringstream __sstream;
00097       __sstream 
00098     << "change std::list to std::vector and its initial size from 0 to "
00099     << _M_max_size;
00100       return __sstream.str();
00101     }
00102 
00103     std::size_t
00104     __shift_count()
00105     { return _M_shift_count; }
00106   
00107     std::size_t
00108     __iterate()
00109     { return _M_iterate; }
00110   
00111     float
00112     __list_cost()
00113     { return _M_list_cost; }
00114   
00115     std::size_t
00116     __resize()
00117     { return _M_resize; }
00118   
00119     void
00120     __set_list_cost(float __lc)
00121     { _M_list_cost = __lc; }
00122     
00123     void
00124     __set_vector_cost(float __vc)
00125     { _M_vector_cost = __vc; }
00126     
00127     bool
00128     __is_valid()
00129     { return _M_valid; }
00130     
00131     void
00132     __set_invalid()
00133     { _M_valid = false; }
00134 
00135     void
00136     __opr_insert(std::size_t __shift, std::size_t __size)
00137     {
00138       _M_shift_count += __shift;
00139       _M_max_size = std::max(_M_max_size, __size);
00140     }
00141 
00142     void
00143     __opr_iterate(std::size_t __num)
00144     { _M_iterate += __num;}
00145 
00146     void
00147     __resize(std::size_t __from, std::size_t)
00148     { _M_resize += __from; }
00149 
00150   private:
00151     std::size_t _M_shift_count;
00152     std::size_t _M_iterate;
00153     std::size_t _M_resize;
00154     float _M_list_cost;
00155     float _M_vector_cost;
00156     bool  _M_valid;
00157     std::size_t _M_max_size;
00158   };
00159 
00160   class __list2vector_stack_info 
00161   : public __list2vector_info
00162   {
00163   public:
00164     __list2vector_stack_info(const __list2vector_info& __o) 
00165     : __list2vector_info(__o) {}
00166   };
00167 
00168   class __trace_list_to_vector
00169   : public __trace_base<__list2vector_info, __list2vector_stack_info> 
00170   {
00171   public:
00172     __trace_list_to_vector()
00173     : __trace_base<__list2vector_info, __list2vector_stack_info>()
00174     { __id = "list-to-vector"; }
00175 
00176     ~__trace_list_to_vector() { }
00177 
00178     // Insert a new node at construct with object, callstack and initial size.
00179     void
00180     __insert(__object_t __obj, __stack_t __stack)
00181     { __add_object(__obj, __list2vector_info(__stack)); }
00182 
00183     // Call at destruction/clean to set container final size.
00184     void
00185     __destruct(const void* __obj)
00186     {
00187       if (!__is_on())
00188     return;
00189 
00190       __list2vector_info* __res = __get_object_info(__obj);
00191       if (!__res)
00192     return;
00193 
00194       float __vc = __vector_cost(__res->__shift_count(), __res->__iterate());
00195       float __lc = __list_cost(__res->__shift_count(), __res->__iterate());
00196       __res->__set_vector_cost(__vc);
00197       __res->__set_list_cost(__lc);
00198       __retire_object(__obj);
00199     }
00200 
00201     // Find the node in the live map.
00202     __list2vector_info* __find(const void* __obj);
00203 
00204     // Collect cost of operations.
00205     void
00206     __opr_insert(const void* __obj, std::size_t __shift, std::size_t __size)
00207     {
00208       __list2vector_info* __res = __get_object_info(__obj);
00209       if (__res)
00210     __res->__opr_insert(__shift, __size);
00211     }
00212 
00213     void
00214     __opr_iterate(const void* __obj, std::size_t __num)
00215     {
00216       __list2vector_info* __res = __get_object_info(__obj);
00217       if (__res)
00218     __res->__opr_iterate(__num);
00219     }
00220 
00221     void
00222     __invalid_operator(const void* __obj)
00223     {
00224       __list2vector_info* __res = __get_object_info(__obj);
00225       if (__res)
00226     __res->__set_invalid();
00227     }
00228 
00229     void
00230     __resize(const void* __obj, std::size_t __from, std::size_t __to)
00231     {
00232       __list2vector_info* __res = __get_object_info(__obj);
00233       if (__res)
00234     __res->__resize(__from, __to);
00235     }
00236 
00237     float
00238     __vector_cost(std::size_t __shift, std::size_t __iterate)
00239     {
00240       // The resulting vector will use a 'reserve' method.
00241       return (__shift
00242           * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value
00243           + __iterate
00244           * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value); 
00245     }
00246 
00247     float
00248     __list_cost(std::size_t __shift, std::size_t __iterate)
00249     {
00250       return (__shift
00251           * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value
00252           + __iterate
00253           * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value); 
00254     }
00255   };
00256 
00257 
00258   inline void
00259   __trace_list_to_vector_init()
00260   { _GLIBCXX_PROFILE_DATA(_S_list_to_vector) = new __trace_list_to_vector(); }
00261 
00262   inline void
00263   __trace_list_to_vector_report(FILE* __f, __warning_vector_t& __warnings)
00264   {
00265     if (_GLIBCXX_PROFILE_DATA(_S_list_to_vector))
00266       {
00267     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->
00268       __collect_warnings(__warnings);
00269     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__write(__f);
00270       }
00271   }
00272 
00273   inline void
00274   __trace_list_to_vector_construct(const void* __obj)
00275   {
00276     if (!__profcxx_init())
00277       return;
00278 
00279     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__insert(__obj, __get_stack());
00280   }
00281 
00282   inline void
00283   __trace_list_to_vector_destruct(const void* __obj)
00284   {
00285     if (!__profcxx_init())
00286       return;
00287 
00288     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__destruct(__obj);
00289   }
00290 
00291   inline void
00292   __trace_list_to_vector_insert(const void* __obj, 
00293                 std::size_t __shift, std::size_t __size)
00294   {
00295     if (!__profcxx_init())
00296       return;
00297 
00298     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__opr_insert(__obj, __shift, 
00299                                __size);
00300   }
00301 
00302   inline void
00303   __trace_list_to_vector_iterate(const void* __obj, std::size_t __num = 1)
00304   {
00305     if (!__profcxx_init())
00306       return;
00307 
00308     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__opr_iterate(__obj, __num);
00309   }
00310 
00311   inline void
00312   __trace_list_to_vector_invalid_operator(const void* __obj)
00313   {
00314     if (!__profcxx_init())
00315       return;
00316 
00317     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__invalid_operator(__obj);
00318   }
00319 
00320   inline void
00321   __trace_list_to_vector_resize(const void* __obj, 
00322                 std::size_t __from, std::size_t __to)
00323   {
00324     if (!__profcxx_init())
00325       return;
00326 
00327     _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__resize(__obj, __from, __to);
00328   }
00329 
00330 } // namespace __gnu_profile
00331 #endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H__ */