libstdc++
profiler_container_size.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Copyright (C) 2009, 2010, 2011 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_container_size.h
00032  *  @brief Diagnostics for container sizes.
00033  */
00034 
00035 // Written by Lixia Liu and Silvius Rus.
00036 
00037 #ifndef _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H
00038 #define _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_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 container size instrumentation line in the object table.  */
00049   class __container_size_info
00050   : public __object_info_base 
00051   {
00052   public:
00053     __container_size_info()
00054     : _M_init(0), _M_max(0), _M_min(0), _M_total(0), _M_item_min(0),
00055       _M_item_max(0), _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0) 
00056     { }
00057 
00058     __container_size_info(const __container_size_info& __o)
00059     : __object_info_base(__o), _M_init(__o._M_init), _M_max(__o._M_max),
00060       _M_min(__o._M_min), _M_total(__o._M_total),
00061       _M_item_min(__o._M_item_min), _M_item_max(__o._M_item_max),
00062       _M_item_total(__o._M_item_total), _M_count(__o._M_count),
00063       _M_resize(__o._M_resize), _M_cost(__o._M_cost)
00064     { }
00065 
00066     __container_size_info(__stack_t __stack, std::size_t __num)
00067     : __object_info_base(__stack), _M_init(__num), _M_max(__num),
00068       _M_min(0), _M_total(0), _M_item_min(0), _M_item_max(0),
00069       _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0)
00070     { }
00071 
00072     virtual ~__container_size_info() { }
00073 
00074     void
00075     __write(FILE* __f) const
00076     {
00077       std::fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n", 
00078            _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max,
00079            _M_total, _M_item_min, _M_item_max, _M_item_total);
00080     }
00081 
00082     float
00083     __magnitude() const
00084     { return static_cast<float>(_M_cost); }
00085 
00086     std::string
00087     __advice() const
00088     {
00089       std::stringstream __message;
00090       if (_M_init < _M_item_max)
00091     __message << "change initial container size from " << _M_init
00092           << " to " << _M_item_max;
00093       return __message.str();
00094     }
00095 
00096     void
00097     __merge(const __container_size_info& __o)
00098     {
00099       _M_init        = std::max(_M_init, __o._M_init);
00100       _M_max         = std::max(_M_max, __o._M_max);
00101       _M_item_max    = std::max(_M_item_max, __o._M_item_max);
00102       _M_min         = std::min(_M_min, __o._M_min);
00103       _M_item_min    = std::min(_M_item_min, __o._M_item_min);
00104       _M_total      += __o._M_total;
00105       _M_item_total += __o._M_item_total;
00106       _M_count      += __o._M_count;
00107       _M_cost       += __o._M_cost;
00108       _M_resize     += __o._M_resize;
00109     }
00110 
00111     // Call if a container is destructed or cleaned.
00112     void
00113     __destruct(std::size_t __num, std::size_t __inum)
00114     {
00115       _M_max = std::max(_M_max, __num);
00116       _M_item_max = std::max(_M_item_max, __inum);
00117       if (_M_min == 0)
00118     {
00119       _M_min = __num; 
00120       _M_item_min = __inum;
00121     }
00122       else
00123     {
00124       _M_min = std::min(_M_min, __num);
00125       _M_item_min = std::min(_M_item_min, __inum);
00126     }
00127       _M_total += __num;
00128       _M_item_total += __inum;
00129       _M_count += 1;
00130     }
00131 
00132     // Estimate the cost of resize/rehash. 
00133     float
00134     __resize_cost(std::size_t __from, std::size_t)
00135     { return __from; }
00136 
00137     // Call if container is resized.
00138     void
00139     __resize(std::size_t __from, std::size_t __to)
00140     {
00141       _M_cost += this->__resize_cost(__from, __to);
00142       _M_resize += 1;
00143       _M_max = std::max(_M_max, __to);
00144     }
00145 
00146   private:
00147     std::size_t _M_init;
00148     std::size_t _M_max;  // range of # buckets
00149     std::size_t _M_min;
00150     std::size_t _M_total;
00151     std::size_t _M_item_min;  // range of # items
00152     std::size_t _M_item_max;
00153     std::size_t _M_item_total;
00154     std::size_t _M_count;
00155     std::size_t _M_resize;
00156     std::size_t _M_cost;
00157   };
00158 
00159 
00160   /** @brief A container size instrumentation line in the stack table.  */
00161   class __container_size_stack_info
00162   : public __container_size_info
00163   {
00164   public:
00165     __container_size_stack_info(const __container_size_info& __o)
00166     : __container_size_info(__o) { }
00167   };
00168 
00169   
00170   /** @brief Container size instrumentation trace producer.  */
00171   class __trace_container_size
00172   : public __trace_base<__container_size_info, __container_size_stack_info> 
00173   {
00174   public:
00175     ~__trace_container_size() { }
00176 
00177     __trace_container_size()
00178     : __trace_base<__container_size_info, __container_size_stack_info>() { };
00179 
00180     // Insert a new node at construct with object, callstack and initial size. 
00181     void
00182     __insert(const __object_t __obj, __stack_t __stack, std::size_t __num)
00183     { __add_object(__obj, __container_size_info(__stack, __num)); }
00184 
00185     // XXX Undefined?
00186     void
00187     __construct(const void* __obj, std::size_t __inum);
00188   
00189     // Call at destruction/clean to set container final size.
00190     void
00191     __destruct(const void* __obj, std::size_t __num, std::size_t __inum)
00192     {
00193       if (!__is_on())
00194     return;
00195 
00196       __object_t __obj_handle = static_cast<__object_t>(__obj);
00197 
00198       __container_size_info* __object_info = __get_object_info(__obj_handle);
00199       if (!__object_info)
00200     return;
00201 
00202       __object_info->__destruct(__num, __inum);
00203       __retire_object(__obj_handle);
00204     }
00205 
00206     // Call at resize to set resize/cost information.
00207     void
00208     __resize(const void* __obj, int __from, int __to)
00209     {
00210       if (!__is_on())
00211     return;
00212 
00213       __container_size_info* __object_info = __get_object_info(__obj);
00214       if (!__object_info)
00215     return;
00216 
00217       __object_info->__resize(__from, __to);
00218     }
00219   };
00220 
00221 } // namespace __gnu_profile
00222 #endif /* _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H */