// -*- C++ -*-
//
-// Copyright (C) 2009 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// reasons why the executable file might be covered by the GNU General
// Public License.
-/** @file profile/impl/profiler_trace.h
+/** @file profile/impl/profiler_container_size.h
* @brief Diagnostics for container sizes.
*/
// Written by Lixia Liu and Silvius Rus.
-#ifndef PROFCXX_PROFILER_CONTAINER_SIZE_H__
-#define PROFCXX_PROFILER_CONTAINER_SIZE_H__ 1
+#ifndef _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H
+#define _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H 1
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-#include <cstdlib>
-#include <cstdio>
-#include <cstring>
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#endif
+#include <sstream>
#include "profile/impl/profiler.h"
#include "profile/impl/profiler_node.h"
namespace __gnu_profile
{
-
-/** @brief A container size instrumentation line in the object table. */
-class __container_size_info: public __object_info_base
-{
- public:
- __container_size_info();
- __container_size_info(const __container_size_info& __o);
- __container_size_info(__stack_t __stack, size_t __num);
- virtual ~__container_size_info() {}
-
- void __write(FILE* f) const;
- float __magnitude() const { return static_cast<float>(_M_cost); }
- const char* __advice() const;
-
- void __merge(const __container_size_info& __o);
- // Call if a container is destructed or cleaned.
- void __destruct(size_t __num, size_t __inum);
- // Estimate the cost of resize/rehash.
- float __resize_cost(size_t __from, size_t __to) { return __from; }
- // Call if container is resized.
- void __resize(size_t __from, size_t __to);
-
- private:
- size_t _M_init;
- size_t _M_max; // range of # buckets
- size_t _M_min;
- size_t _M_total;
- size_t _M_item_min; // range of # items
- size_t _M_item_max;
- size_t _M_item_total;
- size_t _M_count;
- size_t _M_resize;
- size_t _M_cost;
-};
-
-inline const char* __container_size_info::__advice() const
-{
- const size_t __max_chars_size_t_printed = 20;
- const char* __message_pattern =
- "change initial container size from %d to %d";
- size_t __message_size = (strlen(__message_pattern)
- + 2 * __max_chars_size_t_printed
- - 2 * 2);
- char* __message = new char[__message_size + 1];
-
- if (_M_init < _M_item_max)
- snprintf(__message, __message_size, __message_pattern, _M_init,
- _M_item_max);
- else
- snprintf(__message, __message_size, __message_pattern, _M_init,
- _M_item_max);
-
- return __message;
-}
-
-inline void __container_size_info::__destruct(size_t __num, size_t __inum)
-{
- _M_max = __max(_M_max, __num);
- _M_item_max = __max(_M_item_max, __inum);
- if (_M_min == 0) {
- _M_min = __num;
- _M_item_min = __inum;
- } else {
- _M_min = __min(_M_min, __num);
- _M_item_min = __min(_M_item_min, __inum);
- }
- _M_total += __num;
- _M_item_total += __inum;
- _M_count += 1;
-}
-
-inline void __container_size_info::__resize(size_t __from, size_t __to)
-{
- _M_cost += this->__resize_cost(__from, __to);
- _M_resize += 1;
- _M_max = __max(_M_max, __to);
-}
-
-inline __container_size_info::__container_size_info(__stack_t __stack,
- size_t __num)
- : __object_info_base(__stack), _M_init(0), _M_max(0), _M_item_max(0),
- _M_min(0), _M_item_min(0), _M_total(0), _M_item_total(0), _M_cost(0),
- _M_count(0), _M_resize(0)
-{
- _M_init = _M_max = __num;
- _M_item_min = _M_item_max = _M_item_total = _M_total = 0;
- _M_min = 0;
- _M_count = 0;
- _M_resize = 0;
-}
-
-inline void __container_size_info::__merge(const __container_size_info& __o)
-{
- _M_init = __max(_M_init, __o._M_init);
- _M_max = __max(_M_max, __o._M_max);
- _M_item_max = __max(_M_item_max, __o._M_item_max);
- _M_min = __min(_M_min, __o._M_min);
- _M_item_min = __min(_M_item_min, __o._M_item_min);
- _M_total += __o._M_total;
- _M_item_total += __o._M_item_total;
- _M_count += __o._M_count;
- _M_cost += __o._M_cost;
- _M_resize += __o._M_resize;
-}
-
-inline __container_size_info::__container_size_info()
- : _M_init(0), _M_max(0), _M_item_max(0), _M_min(0), _M_item_min(0),
- _M_total(0), _M_item_total(0), _M_cost(0), _M_count(0), _M_resize(0)
-{
-}
-
-inline __container_size_info::__container_size_info(
- const __container_size_info& __o)
- : __object_info_base(__o)
-{
- _M_init = __o._M_init;
- _M_max = __o._M_max;
- _M_item_max = __o._M_item_max;
- _M_min = __o._M_min;
- _M_item_min = __o._M_item_min;
- _M_total = __o._M_total;
- _M_item_total = __o._M_item_total;
- _M_cost = __o._M_cost;
- _M_count = __o._M_count;
- _M_resize = __o._M_resize;
-}
-
-/** @brief A container size instrumentation line in the stack table. */
-class __container_size_stack_info: public __container_size_info
-{
- public:
- __container_size_stack_info(const __container_size_info& __o)
- : __container_size_info(__o) {}
-};
-
-/** @brief Container size instrumentation trace producer. */
-class __trace_container_size
- : public __trace_base<__container_size_info, __container_size_stack_info>
-{
- public:
- ~__trace_container_size() {}
- __trace_container_size()
- : __trace_base<__container_size_info, __container_size_stack_info>() {};
-
- // Insert a new node at construct with object, callstack and initial size.
- void __insert(const __object_t __obj, __stack_t __stack, size_t __num);
- // Call at destruction/clean to set container final size.
- void __destruct(const void* __obj, size_t __num, size_t __inum);
- void __construct(const void* __obj, size_t __inum);
- // Call at resize to set resize/cost information.
- void __resize(const void* __obj, int __from, int __to);
-};
-
-inline void __trace_container_size::__insert(const __object_t __obj,
- __stack_t __stack, size_t __num)
-{
- __add_object(__obj, __container_size_info(__stack, __num));
-}
-
-inline void __container_size_info::__write(FILE* __f) const
-{
- fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n",
- _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max, _M_total,
- _M_item_min, _M_item_max, _M_item_total);
-}
-
-inline void __trace_container_size::__destruct(const void* __obj,
- size_t __num, size_t __inum)
-{
- if (!__is_on()) return;
-
- __object_t __obj_handle = static_cast<__object_t>(__obj);
-
- __container_size_info* __object_info = __get_object_info(__obj_handle);
- if (!__object_info)
- return;
-
- __object_info->__destruct(__num, __inum);
- __retire_object(__obj_handle);
-}
-
-inline void __trace_container_size::__resize(const void* __obj, int __from,
- int __to)
-{
- if (!__is_on()) return;
-
- __container_size_info* __object_info = __get_object_info(__obj);
- if (!__object_info)
- return;
-
- __object_info->__resize(__from, __to);
-}
+ /** @brief A container size instrumentation line in the object table. */
+ class __container_size_info
+ : public __object_info_base
+ {
+ public:
+ __container_size_info()
+ : _M_init(0), _M_max(0), _M_min(0), _M_total(0), _M_item_min(0),
+ _M_item_max(0), _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0)
+ { }
+
+ __container_size_info(const __container_size_info& __o)
+ : __object_info_base(__o), _M_init(__o._M_init), _M_max(__o._M_max),
+ _M_min(__o._M_min), _M_total(__o._M_total),
+ _M_item_min(__o._M_item_min), _M_item_max(__o._M_item_max),
+ _M_item_total(__o._M_item_total), _M_count(__o._M_count),
+ _M_resize(__o._M_resize), _M_cost(__o._M_cost)
+ { }
+
+ __container_size_info(__stack_t __stack, std::size_t __num)
+ : __object_info_base(__stack), _M_init(__num), _M_max(__num),
+ _M_min(0), _M_total(0), _M_item_min(0), _M_item_max(0),
+ _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0)
+ { }
+
+ virtual ~__container_size_info() { }
+
+ void
+ __write(FILE* __f) const
+ {
+ std::fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n",
+ _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max,
+ _M_total, _M_item_min, _M_item_max, _M_item_total);
+ }
+
+ float
+ __magnitude() const
+ { return static_cast<float>(_M_cost); }
+
+ std::string
+ __advice() const
+ {
+ std::stringstream __message;
+ if (_M_init < _M_item_max)
+ __message << "change initial container size from " << _M_init
+ << " to " << _M_item_max;
+ return __message.str();
+ }
+
+ void
+ __merge(const __container_size_info& __o)
+ {
+ _M_init = std::max(_M_init, __o._M_init);
+ _M_max = std::max(_M_max, __o._M_max);
+ _M_item_max = std::max(_M_item_max, __o._M_item_max);
+ _M_min = std::min(_M_min, __o._M_min);
+ _M_item_min = std::min(_M_item_min, __o._M_item_min);
+ _M_total += __o._M_total;
+ _M_item_total += __o._M_item_total;
+ _M_count += __o._M_count;
+ _M_cost += __o._M_cost;
+ _M_resize += __o._M_resize;
+ }
+
+ // Call if a container is destructed or cleaned.
+ void
+ __destruct(std::size_t __num, std::size_t __inum)
+ {
+ _M_max = std::max(_M_max, __num);
+ _M_item_max = std::max(_M_item_max, __inum);
+ if (_M_min == 0)
+ {
+ _M_min = __num;
+ _M_item_min = __inum;
+ }
+ else
+ {
+ _M_min = std::min(_M_min, __num);
+ _M_item_min = std::min(_M_item_min, __inum);
+ }
+ _M_total += __num;
+ _M_item_total += __inum;
+ _M_count += 1;
+ }
+
+ // Estimate the cost of resize/rehash.
+ float
+ __resize_cost(std::size_t __from, std::size_t)
+ { return __from; }
+
+ // Call if container is resized.
+ void
+ __resize(std::size_t __from, std::size_t __to)
+ {
+ _M_cost += this->__resize_cost(__from, __to);
+ _M_resize += 1;
+ _M_max = std::max(_M_max, __to);
+ }
+
+ private:
+ std::size_t _M_init;
+ std::size_t _M_max; // range of # buckets
+ std::size_t _M_min;
+ std::size_t _M_total;
+ std::size_t _M_item_min; // range of # items
+ std::size_t _M_item_max;
+ std::size_t _M_item_total;
+ std::size_t _M_count;
+ std::size_t _M_resize;
+ std::size_t _M_cost;
+ };
+
+
+ /** @brief A container size instrumentation line in the stack table. */
+ class __container_size_stack_info
+ : public __container_size_info
+ {
+ public:
+ __container_size_stack_info(const __container_size_info& __o)
+ : __container_size_info(__o) { }
+ };
+
+
+ /** @brief Container size instrumentation trace producer. */
+ class __trace_container_size
+ : public __trace_base<__container_size_info, __container_size_stack_info>
+ {
+ public:
+ ~__trace_container_size() { }
+
+ __trace_container_size()
+ : __trace_base<__container_size_info, __container_size_stack_info>() { };
+
+ // Insert a new node at construct with object, callstack and initial size.
+ void
+ __insert(const __object_t __obj, __stack_t __stack, std::size_t __num)
+ { __add_object(__obj, __container_size_info(__stack, __num)); }
+
+ // XXX Undefined?
+ void
+ __construct(const void* __obj, std::size_t __inum);
+
+ // Call at destruction/clean to set container final size.
+ void
+ __destruct(const void* __obj, std::size_t __num, std::size_t __inum)
+ {
+ if (!__is_on())
+ return;
+
+ __object_t __obj_handle = static_cast<__object_t>(__obj);
+
+ __container_size_info* __object_info = __get_object_info(__obj_handle);
+ if (!__object_info)
+ return;
+
+ __object_info->__destruct(__num, __inum);
+ __retire_object(__obj_handle);
+ }
+
+ // Call at resize to set resize/cost information.
+ void
+ __resize(const void* __obj, int __from, int __to)
+ {
+ if (!__is_on())
+ return;
+
+ __container_size_info* __object_info = __get_object_info(__obj);
+ if (!__object_info)
+ return;
+
+ __object_info->__resize(__from, __to);
+ }
+ };
} // namespace __gnu_profile
-#endif /* PROFCXX_PROFILER_CONTAINER_SIZE_H__ */
+#endif /* _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H */