Home | History | Annotate | Download | only in impl
      1 // -*- C++ -*-
      2 //
      3 // Copyright (C) 2009, 2010, 2011 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_container_size.h
     32  *  @brief Diagnostics for container sizes.
     33  */
     34 
     35 // Written by Lixia Liu and Silvius Rus.
     36 
     37 #ifndef _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H
     38 #define _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_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 container size instrumentation line in the object table.  */
     49   class __container_size_info
     50   : public __object_info_base
     51   {
     52   public:
     53     __container_size_info()
     54     : _M_init(0), _M_max(0), _M_min(0), _M_total(0), _M_item_min(0),
     55       _M_item_max(0), _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0)
     56     { }
     57 
     58     __container_size_info(const __container_size_info& __o)
     59     : __object_info_base(__o), _M_init(__o._M_init), _M_max(__o._M_max),
     60       _M_min(__o._M_min), _M_total(__o._M_total),
     61       _M_item_min(__o._M_item_min), _M_item_max(__o._M_item_max),
     62       _M_item_total(__o._M_item_total), _M_count(__o._M_count),
     63       _M_resize(__o._M_resize), _M_cost(__o._M_cost)
     64     { }
     65 
     66     __container_size_info(__stack_t __stack, std::size_t __num)
     67     : __object_info_base(__stack), _M_init(__num), _M_max(__num),
     68       _M_min(0), _M_total(0), _M_item_min(0), _M_item_max(0),
     69       _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0)
     70     { }
     71 
     72     virtual ~__container_size_info() { }
     73 
     74     void
     75     __write(FILE* __f) const
     76     {
     77       std::fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n",
     78 		   _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max,
     79 		   _M_total, _M_item_min, _M_item_max, _M_item_total);
     80     }
     81 
     82     float
     83     __magnitude() const
     84     { return static_cast<float>(_M_cost); }
     85 
     86     std::string
     87     __advice() const
     88     {
     89       std::stringstream __message;
     90       if (_M_init < _M_item_max)
     91 	__message << "change initial container size from " << _M_init
     92 		  << " to " << _M_item_max;
     93       return __message.str();
     94     }
     95 
     96     void
     97     __merge(const __container_size_info& __o)
     98     {
     99       _M_init        = std::max(_M_init, __o._M_init);
    100       _M_max         = std::max(_M_max, __o._M_max);
    101       _M_item_max    = std::max(_M_item_max, __o._M_item_max);
    102       _M_min         = std::min(_M_min, __o._M_min);
    103       _M_item_min    = std::min(_M_item_min, __o._M_item_min);
    104       _M_total      += __o._M_total;
    105       _M_item_total += __o._M_item_total;
    106       _M_count      += __o._M_count;
    107       _M_cost       += __o._M_cost;
    108       _M_resize     += __o._M_resize;
    109     }
    110 
    111     // Call if a container is destructed or cleaned.
    112     void
    113     __destruct(std::size_t __num, std::size_t __inum)
    114     {
    115       _M_max = std::max(_M_max, __num);
    116       _M_item_max = std::max(_M_item_max, __inum);
    117       if (_M_min == 0)
    118 	{
    119 	  _M_min = __num;
    120 	  _M_item_min = __inum;
    121 	}
    122       else
    123 	{
    124 	  _M_min = std::min(_M_min, __num);
    125 	  _M_item_min = std::min(_M_item_min, __inum);
    126 	}
    127       _M_total += __num;
    128       _M_item_total += __inum;
    129       _M_count += 1;
    130     }
    131 
    132     // Estimate the cost of resize/rehash.
    133     float
    134     __resize_cost(std::size_t __from, std::size_t)
    135     { return __from; }
    136 
    137     // Call if container is resized.
    138     void
    139     __resize(std::size_t __from, std::size_t __to)
    140     {
    141       _M_cost += this->__resize_cost(__from, __to);
    142       _M_resize += 1;
    143       _M_max = std::max(_M_max, __to);
    144     }
    145 
    146   private:
    147     std::size_t _M_init;
    148     std::size_t _M_max;  // range of # buckets
    149     std::size_t _M_min;
    150     std::size_t _M_total;
    151     std::size_t _M_item_min;  // range of # items
    152     std::size_t _M_item_max;
    153     std::size_t _M_item_total;
    154     std::size_t _M_count;
    155     std::size_t _M_resize;
    156     std::size_t _M_cost;
    157   };
    158 
    159 
    160   /** @brief A container size instrumentation line in the stack table.  */
    161   class __container_size_stack_info
    162   : public __container_size_info
    163   {
    164   public:
    165     __container_size_stack_info(const __container_size_info& __o)
    166     : __container_size_info(__o) { }
    167   };
    168 
    169 
    170   /** @brief Container size instrumentation trace producer.  */
    171   class __trace_container_size
    172   : public __trace_base<__container_size_info, __container_size_stack_info>
    173   {
    174   public:
    175     ~__trace_container_size() { }
    176 
    177     __trace_container_size()
    178     : __trace_base<__container_size_info, __container_size_stack_info>() { };
    179 
    180     // Insert a new node at construct with object, callstack and initial size.
    181     void
    182     __insert(const __object_t __obj, __stack_t __stack, std::size_t __num)
    183     { __add_object(__obj, __container_size_info(__stack, __num)); }
    184 
    185     // XXX Undefined?
    186     void
    187     __construct(const void* __obj, std::size_t __inum);
    188 
    189     // Call at destruction/clean to set container final size.
    190     void
    191     __destruct(const void* __obj, std::size_t __num, std::size_t __inum)
    192     {
    193       if (!__is_on())
    194 	return;
    195 
    196       __object_t __obj_handle = static_cast<__object_t>(__obj);
    197 
    198       __container_size_info* __object_info = __get_object_info(__obj_handle);
    199       if (!__object_info)
    200 	return;
    201 
    202       __object_info->__destruct(__num, __inum);
    203       __retire_object(__obj_handle);
    204     }
    205 
    206     // Call at resize to set resize/cost information.
    207     void
    208     __resize(const void* __obj, int __from, int __to)
    209     {
    210       if (!__is_on())
    211 	return;
    212 
    213       __container_size_info* __object_info = __get_object_info(__obj);
    214       if (!__object_info)
    215 	return;
    216 
    217       __object_info->__resize(__from, __to);
    218     }
    219   };
    220 
    221 } // namespace __gnu_profile
    222 #endif /* _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H */
    223