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