diff mbox

[1/2] Memory statistics enhancement.

Message ID 5575AE35.1050501@suse.cz
State New
Headers show

Commit Message

Martin Liška June 8, 2015, 3:01 p.m. UTC
On 06/01/2015 06:16 PM, mliska wrote:
> Hi.
> 
> Following 2 patches improve memory statistics infrastructure. First one
> ports pool allocator to the new infrastructure. And the second one makes
> column alignment properly.
> 
> Both can bootstrap on x86_64-linux-pc and survive regression tests.
> 
> Ready for trunk?
> Thank you,
> Martin
> 
> Port pool-allocator memory stats to a new infrastructure.
> 
> gcc/ChangeLog:
> 
> 2015-06-02  Martin Liska  <mliska@suse.cz>
> 
> 	* alloc-pool.c (allocate_pool_descriptor): Remove.
> 	(struct pool_output_info): Likewise.
> 	(print_alloc_pool_statistics): Likewise.
> 	(dump_alloc_pool_statistics): Likewise.
> 	* alloc-pool.h (struct pool_usage): New struct.
> 	(pool_allocator::initialize): Change usage of memory statistics
> 	to a new interface.
> 	(pool_allocator::release): Likewise.
> 	(pool_allocator::allocate): Likewise.
> 	(pool_allocator::remove): Likewise.
> 	* mem-stats-traits.h (enum mem_alloc_origin): Add new enum value
> 	for a pool allocator.
> 	* mem-stats.h (struct mem_location): Add new ctor.
> 	(struct mem_usage): Add counter for number of
> 	instances.
> 	(mem_alloc_description::register_descriptor): New overload of
> 	the function.
> ---
>  gcc/alloc-pool.c       |  60 +----------------------------
>  gcc/alloc-pool.h       | 102 +++++++++++++++++++++++++++++++++++++++----------
>  gcc/mem-stats-traits.h |   3 +-
>  gcc/mem-stats.h        |  69 ++++++++++++++++++++++-----------
>  4 files changed, 132 insertions(+), 102 deletions(-)
> 
> diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
> index e9fdc86..601c2b7 100644
> --- a/gcc/alloc-pool.c
> +++ b/gcc/alloc-pool.c
> @@ -26,70 +26,14 @@ along with GCC; see the file COPYING3.  If not see
>  #include "hash-map.h"
>  
>  ALLOC_POOL_ID_TYPE last_id;
> -
> -/* Hashtable mapping alloc_pool names to descriptors.  */
> -hash_map<const char *, alloc_pool_descriptor> *alloc_pool_hash;
> -
> -struct alloc_pool_descriptor *
> -allocate_pool_descriptor (const char *name)
> -{
> -  if (!alloc_pool_hash)
> -    alloc_pool_hash = new hash_map<const char *, alloc_pool_descriptor> (10,
> -									 false,
> -									 false);
> -
> -  return &alloc_pool_hash->get_or_insert (name);
> -}
> -
> -/* Output per-alloc_pool statistics.  */
> -
> -/* Used to accumulate statistics about alloc_pool sizes.  */
> -struct pool_output_info
> -{
> -  unsigned long total_created;
> -  unsigned long total_allocated;
> -};
> -
> -/* Called via hash_map.traverse.  Output alloc_pool descriptor pointed out by
> -   SLOT and update statistics.  */
> -bool
> -print_alloc_pool_statistics (const char *const &name,
> -			     const alloc_pool_descriptor &d,
> -			     struct pool_output_info *i)
> -{
> -  if (d.allocated)
> -    {
> -      fprintf (stderr,
> -	       "%-22s %6d %10lu %10lu(%10lu) %10lu(%10lu) %10lu(%10lu)\n",
> -	       name, d.elt_size, d.created, d.allocated,
> -	       d.allocated / d.elt_size, d.peak, d.peak / d.elt_size,
> -	       d.current, d.current / d.elt_size);
> -      i->total_allocated += d.allocated;
> -      i->total_created += d.created;
> -    }
> -  return 1;
> -}
> +mem_alloc_description<pool_usage> pool_allocator_usage;
>  
>  /* Output per-alloc_pool memory usage statistics.  */
>  void
>  dump_alloc_pool_statistics (void)
>  {
> -  struct pool_output_info info;
> -
>    if (! GATHER_STATISTICS)
>      return;
>  
> -  if (!alloc_pool_hash)
> -    return;
> -
> -  fprintf (stderr, "\nAlloc-pool Kind         Elt size  Pools  Allocated (elts)            Peak (elts)            Leak (elts)\n");
> -  fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
> -  info.total_created = 0;
> -  info.total_allocated = 0;
> -  alloc_pool_hash->traverse <struct pool_output_info *,
> -			     print_alloc_pool_statistics> (&info);
> -  fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
> -  fprintf (stderr, "%-22s           %7lu %10lu\n",
> -	   "Total", info.total_created, info.total_allocated);
> -  fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
> +  pool_allocator_usage.dump (ALLOC_POOL);
>  }
> diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h
> index 96a1342..a1727ce 100644
> --- a/gcc/alloc-pool.h
> +++ b/gcc/alloc-pool.h
> @@ -26,6 +26,71 @@ extern void dump_alloc_pool_statistics (void);
>  
>  typedef unsigned long ALLOC_POOL_ID_TYPE;
>  
> +/* Pool allocator memory usage.  */
> +struct pool_usage: public mem_usage
> +{
> +  /* Default contructor.  */
> +  pool_usage (): m_element_size (0), m_pool_name ("") {}
> +  /* Constructor.  */
> +  pool_usage (size_t allocated, size_t times, size_t peak,
> +	      size_t instances, size_t element_size,
> +	      const char *pool_name)
> +    : mem_usage (allocated, times, peak, instances),
> +      m_element_size (element_size),
> +      m_pool_name (pool_name) {}
> +
> +  /* Sum the usage with SECOND usage.  */
> +  pool_usage operator+ (const pool_usage &second)
> +  {
> +    return pool_usage (m_allocated + second.m_allocated,
> +			     m_times + second.m_times,
> +			     m_peak + second.m_peak,
> +			     m_instances + second.m_instances,
> +			     m_element_size, m_pool_name);
> +  }
> +
> +  /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
> +  inline void dump (mem_location *loc, mem_usage &total) const
> +  {
> +    char s[4096];
> +    sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
> +	     loc->m_line, loc->m_function);
> +
> +    s[48] = '\0';
> +
> +    fprintf (stderr, "%-32s%-48s %6li%10li:%5.1f%%%10li%10li:%5.1f%%%12li\n",
> +	     m_pool_name, s, (long)m_instances,
> +	     (long)m_allocated, get_percent (m_allocated, total.m_allocated),
> +	     (long)m_peak, (long)m_times,
> +	     get_percent (m_times, total.m_times),
> +	     (long)m_element_size);
> +  }
> +
> +  /* Dump header with NAME.  */
> +  static inline void dump_header (const char *name)
> +  {
> +    fprintf (stderr, "%-32s%-48s %6s%11s%16s%17s%12s\n", "Pool name", name,
> +	     "Pools", "Leak", "Peak", "Times", "Elt size");
> +    print_dash_line ();
> +  }
> +
> +  /* Dump footer.  */
> +  inline void dump_footer ()
> +  {
> +    print_dash_line ();
> +    fprintf (stderr, "%s%75li%10li\n", "Total", (long)m_instances,
> +	     (long)m_allocated);
> +    print_dash_line ();
> +  }
> +
> +  /* Element size.  */
> +  size_t m_element_size;
> +  /* Pool name.  */
> +  const char *m_pool_name;
> +};
> +
> +extern mem_alloc_description<pool_usage> pool_allocator_usage;
> +
>  /* Type based memory pool allocator.  */
>  template <typename T>
>  class pool_allocator
> @@ -35,7 +100,7 @@ public:
>       has NUM elements.  The allocator support EXTRA_SIZE and can
>       potentially IGNORE_TYPE_SIZE.  */
>    pool_allocator (const char *name, size_t num, size_t extra_size = 0,
> -		  bool ignore_type_size = false);
> +		  bool ignore_type_size = false CXX_MEM_STAT_INFO);
>    ~pool_allocator ();
>    void release ();
>    void release_if_empty ();
> @@ -122,6 +187,8 @@ private:
>    size_t m_extra_size;
>    /* Flag if a pool allocator is initialized.  */
>    bool m_initialized;
> +  /* Memory allocation location.  */
> +  mem_location m_location;
>  };
>  
>  /* Last used ID.  */
> @@ -151,19 +218,16 @@ struct alloc_pool_descriptor
>  /* Hashtable mapping alloc_pool names to descriptors.  */
>  extern hash_map<const char *, alloc_pool_descriptor> *alloc_pool_hash;
>  
> -/* For given name, return descriptor, create new if needed.  */
> -alloc_pool_descriptor *
> -allocate_pool_descriptor (const char *name);
> -
>  template <typename T>
>  inline
>  pool_allocator<T>::pool_allocator (const char *name, size_t num,
> -				   size_t extra_size, bool ignore_type_size):
> +				   size_t extra_size, bool ignore_type_size
> +				   MEM_STAT_DECL):
>    m_name (name), m_elts_per_block (num), m_returned_free_list (NULL),
>    m_virgin_free_list (NULL), m_virgin_elts_remaining (0), m_elts_allocated (0),
>    m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL),
>    m_ignore_type_size (ignore_type_size), m_extra_size (extra_size),
> -  m_initialized (false) {}
> +  m_initialized (false), m_location (ALLOC_POOL, false PASS_MEM_STAT) {}
>  
>  /* Initialize a pool allocator.  */
>  
> @@ -196,9 +260,11 @@ pool_allocator<T>::initialize ()
>  
>    if (GATHER_STATISTICS)
>      {
> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
> -      desc->elt_size = size;
> -      desc->created++;
> +      pool_usage *u = pool_allocator_usage.register_descriptor
> +	(this, new mem_location (m_location));
> +
> +      u->m_element_size = m_elt_size;
> +      u->m_pool_name = m_name;
>      }
>  
>    /* List header size should be a multiple of 8.  */
> @@ -235,10 +301,10 @@ pool_allocator<T>::release ()
>        free (block);
>      }
>  
> -  if (GATHER_STATISTICS && false)
> +  if (GATHER_STATISTICS)
>      {
> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
> -      desc->current -= (m_elts_allocated - m_elts_free) * m_elt_size;
> +      pool_allocator_usage.release_instance_overhead (this,
> +	(m_elts_allocated - m_elts_free) * m_elt_size);
>      }
>  
>    m_returned_free_list = NULL;
> @@ -279,12 +345,7 @@ pool_allocator<T>::allocate ()
>  
>    if (GATHER_STATISTICS)
>      {
> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
> -
> -      desc->allocated += m_elt_size;
> -      desc->current += m_elt_size;
> -      if (desc->peak < desc->current)
> -	desc->peak = desc->current;
> +      pool_allocator_usage.register_instance_overhead (m_elt_size, this);
>      }
>  
>  #ifdef ENABLE_VALGRIND_ANNOTATIONS
> @@ -383,8 +444,7 @@ pool_allocator<T>::remove (T *object)
>  
>    if (GATHER_STATISTICS)
>      {
> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
> -      desc->current -= m_elt_size;
> +      pool_allocator_usage.release_instance_overhead (this, m_elt_size);
>      }
>  }
>  
> diff --git a/gcc/mem-stats-traits.h b/gcc/mem-stats-traits.h
> index de1614e..f7843f2 100644
> --- a/gcc/mem-stats-traits.h
> +++ b/gcc/mem-stats-traits.h
> @@ -10,11 +10,12 @@ enum mem_alloc_origin
>    VEC,
>    BITMAP,
>    GGC,
> +  ALLOC_POOL,
>    MEM_ALLOC_ORIGIN_LENGTH
>  };
>  
>  /* Verbose names of the memory allocation origin.  */
>  static const char * mem_alloc_origin_names[] = { "Hash tables", "Hash maps",
> -  "Hash sets", "Heap vectors", "Bitmaps", "GGC memory" };
> +  "Hash sets", "Heap vectors", "Bitmaps", "GGC memory", "Allocation pool" };
>  
>  #endif // GCC_MEM_STATS_TRAITS_H
> diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h
> index ac47231..fea68fa 100644
> --- a/gcc/mem-stats.h
> +++ b/gcc/mem-stats.h
> @@ -18,11 +18,16 @@ struct mem_location
>    inline mem_location () {}
>  
>    /* Constructor.  */
> -  inline mem_location (const char *filename, const char *function, int line,
> -		mem_alloc_origin origin, bool ggc):
> +  inline mem_location (mem_alloc_origin origin, bool ggc,
> +		const char *filename = NULL, int line = 0, const char *function = NULL):
>      m_filename (filename), m_function (function), m_line (line), m_origin
>      (origin), m_ggc (ggc) {}
>  
> +  /* Copy constructor.  */
> +  inline mem_location (mem_location &other): m_filename (other.m_filename),
> +    m_function (other.m_function), m_line (other.m_line),
> +    m_origin (other.m_origin), m_ggc (other.m_ggc) {}
> +
>    /* Compute hash value based on file name, function name and line in
>       source code. As there is just a single pointer registered for every
>       constant that points to e.g. the same file name, we can use hash
> @@ -79,11 +84,12 @@ struct mem_location
>  struct mem_usage
>  {
>    /* Default constructor.  */
> -  mem_usage (): m_allocated (0), m_times (0), m_peak (0) {}
> +  mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {}
>  
>    /* Constructor.  */
> -  mem_usage (size_t allocated, size_t times, size_t peak):
> -    m_allocated (allocated), m_times (times), m_peak (peak) {}
> +  mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0):
> +    m_allocated (allocated), m_times (times), m_peak (peak),
> +    m_instances (instances) {}
>  
>    /* Register overhead of SIZE bytes.  */
>    inline void register_overhead (size_t size)
> @@ -108,7 +114,8 @@ struct mem_usage
>    {
>      return mem_usage (m_allocated + second.m_allocated,
>  		      m_times + second.m_times,
> -		      m_peak + second.m_peak);
> +		      m_peak + second.m_peak,
> +		      m_instances + second.m_instances);
>    }
>  
>    /* Comparison operator.  */
> @@ -163,7 +170,7 @@ struct mem_usage
>    /* Print line made of dashes.  */
>    static inline void print_dash_line ()
>    {
> -    fprintf (stderr, "%s\n", std::string (128, '-').c_str ());
> +    fprintf (stderr, "%s\n", std::string (140, '-').c_str ());
>    }
>  
>    /* Dump header with NAME.  */
> @@ -180,6 +187,8 @@ struct mem_usage
>    size_t m_times;
>    /* Peak allocation in bytes.  */
>    size_t m_peak;
> +  /* Number of container instances.  */
> +  size_t m_instances;
>  };
>  
>  /* Memory usage pair that connectes memory usage and number
> @@ -241,9 +250,13 @@ public:
>    /* Return descriptor for instance PTR.  */
>    T *get_descriptor_for_instance (const void *ptr);
>  
> -  /* Register memory allocation descriptor for container PTR. ORIGIN identifies
> +  /* Register memory allocation descriptor for container PTR which is
> +     described by a memory LOCATION.  */
> +  T *register_descriptor (const void *ptr, mem_location *location);
> +
> +  /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
>       type of container and GGC identifes if the allocation is handled in GGC
> -     memory. Each location is identified by file NAME, LINE in source code and
> +     memory.  Each location is identified by file NAME, LINE in source code and
>       FUNCTION name.  */
>    T *register_descriptor (const void *ptr, mem_alloc_origin origin,
>  			  bool ggc, const char *name, int line,
> @@ -321,33 +334,27 @@ mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
>    return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
>  }
>  
> -/* Register memory allocation descriptor for container PTR. ORIGIN identifies
> -   type of container and GGC identifes if the allocation is handled in GGC
> -   memory. Each location is identified by file NAME, LINE in source code and
> -   FUNCTION name.  */
>  
> +  /* Register memory allocation descriptor for container PTR which is
> +     described by a memory LOCATION.  */
>  template <class T>
>  inline T*
>  mem_alloc_description<T>::register_descriptor (const void *ptr,
> -					       mem_alloc_origin origin,
> -					       bool ggc,
> -					       const char *filename,
> -					       int line,
> -					       const char *function)
> +					       mem_location *location)
>  {
> -  mem_location *l = new mem_location (filename, function, line, origin, ggc);
>    T *usage = NULL;
>  
> -  T **slot = m_map->get (l);
> +  T **slot = m_map->get (location);
>    if (slot)
>      {
> -      delete l;
> +      delete location;
>        usage = *slot;
> +      usage->m_instances++;
>      }
>    else
>      {
>        usage = new T ();
> -      m_map->put (l, usage);
> +      m_map->put (location, usage);
>      }
>  
>    if (!m_reverse_map->get (ptr))
> @@ -356,6 +363,24 @@ mem_alloc_description<T>::register_descriptor (const void *ptr,
>    return usage;
>  }
>  
> +/* Register memory allocation descriptor for container PTR.  ORIGIN identifies
> +   type of container and GGC identifes if the allocation is handled in GGC
> +   memory.  Each location is identified by file NAME, LINE in source code and
> +   FUNCTION name.  */
> +
> +template <class T>
> +inline T*
> +mem_alloc_description<T>::register_descriptor (const void *ptr,
> +					       mem_alloc_origin origin,
> +					       bool ggc,
> +					       const char *filename,
> +					       int line,
> +					       const char *function)
> +{
> +  mem_location *l = new mem_location (origin, ggc, filename, line, function);
> +  return register_descriptor (ptr, l);
> +}
> +
>  /* Register instance overhead identified by PTR pointer. Allocation takes
>     SIZE bytes.  */
>  
> 

Hello.

There's a small patch that fixes ICE if a compiler is not built with --enable-gather-mem-stats
and we append -fmem-report to a command line options.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready for trunk?
Thanks,
Martin

Comments

Martin Liška June 16, 2015, 1:16 p.m. UTC | #1
On 06/08/2015 05:01 PM, Martin Liška wrote:
> On 06/01/2015 06:16 PM, mliska wrote:
>> Hi.
>>
>> Following 2 patches improve memory statistics infrastructure. First one
>> ports pool allocator to the new infrastructure. And the second one makes
>> column alignment properly.
>>
>> Both can bootstrap on x86_64-linux-pc and survive regression tests.
>>
>> Ready for trunk?
>> Thank you,
>> Martin
>>
>> Port pool-allocator memory stats to a new infrastructure.
>>
>> gcc/ChangeLog:
>>
>> 2015-06-02  Martin Liska  <mliska@suse.cz>
>>
>> 	* alloc-pool.c (allocate_pool_descriptor): Remove.
>> 	(struct pool_output_info): Likewise.
>> 	(print_alloc_pool_statistics): Likewise.
>> 	(dump_alloc_pool_statistics): Likewise.
>> 	* alloc-pool.h (struct pool_usage): New struct.
>> 	(pool_allocator::initialize): Change usage of memory statistics
>> 	to a new interface.
>> 	(pool_allocator::release): Likewise.
>> 	(pool_allocator::allocate): Likewise.
>> 	(pool_allocator::remove): Likewise.
>> 	* mem-stats-traits.h (enum mem_alloc_origin): Add new enum value
>> 	for a pool allocator.
>> 	* mem-stats.h (struct mem_location): Add new ctor.
>> 	(struct mem_usage): Add counter for number of
>> 	instances.
>> 	(mem_alloc_description::register_descriptor): New overload of
>> 	the function.
>> ---
>>  gcc/alloc-pool.c       |  60 +----------------------------
>>  gcc/alloc-pool.h       | 102 +++++++++++++++++++++++++++++++++++++++----------
>>  gcc/mem-stats-traits.h |   3 +-
>>  gcc/mem-stats.h        |  69 ++++++++++++++++++++++-----------
>>  4 files changed, 132 insertions(+), 102 deletions(-)
>>
>> diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
>> index e9fdc86..601c2b7 100644
>> --- a/gcc/alloc-pool.c
>> +++ b/gcc/alloc-pool.c
>> @@ -26,70 +26,14 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "hash-map.h"
>>  
>>  ALLOC_POOL_ID_TYPE last_id;
>> -
>> -/* Hashtable mapping alloc_pool names to descriptors.  */
>> -hash_map<const char *, alloc_pool_descriptor> *alloc_pool_hash;
>> -
>> -struct alloc_pool_descriptor *
>> -allocate_pool_descriptor (const char *name)
>> -{
>> -  if (!alloc_pool_hash)
>> -    alloc_pool_hash = new hash_map<const char *, alloc_pool_descriptor> (10,
>> -									 false,
>> -									 false);
>> -
>> -  return &alloc_pool_hash->get_or_insert (name);
>> -}
>> -
>> -/* Output per-alloc_pool statistics.  */
>> -
>> -/* Used to accumulate statistics about alloc_pool sizes.  */
>> -struct pool_output_info
>> -{
>> -  unsigned long total_created;
>> -  unsigned long total_allocated;
>> -};
>> -
>> -/* Called via hash_map.traverse.  Output alloc_pool descriptor pointed out by
>> -   SLOT and update statistics.  */
>> -bool
>> -print_alloc_pool_statistics (const char *const &name,
>> -			     const alloc_pool_descriptor &d,
>> -			     struct pool_output_info *i)
>> -{
>> -  if (d.allocated)
>> -    {
>> -      fprintf (stderr,
>> -	       "%-22s %6d %10lu %10lu(%10lu) %10lu(%10lu) %10lu(%10lu)\n",
>> -	       name, d.elt_size, d.created, d.allocated,
>> -	       d.allocated / d.elt_size, d.peak, d.peak / d.elt_size,
>> -	       d.current, d.current / d.elt_size);
>> -      i->total_allocated += d.allocated;
>> -      i->total_created += d.created;
>> -    }
>> -  return 1;
>> -}
>> +mem_alloc_description<pool_usage> pool_allocator_usage;
>>  
>>  /* Output per-alloc_pool memory usage statistics.  */
>>  void
>>  dump_alloc_pool_statistics (void)
>>  {
>> -  struct pool_output_info info;
>> -
>>    if (! GATHER_STATISTICS)
>>      return;
>>  
>> -  if (!alloc_pool_hash)
>> -    return;
>> -
>> -  fprintf (stderr, "\nAlloc-pool Kind         Elt size  Pools  Allocated (elts)            Peak (elts)            Leak (elts)\n");
>> -  fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
>> -  info.total_created = 0;
>> -  info.total_allocated = 0;
>> -  alloc_pool_hash->traverse <struct pool_output_info *,
>> -			     print_alloc_pool_statistics> (&info);
>> -  fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
>> -  fprintf (stderr, "%-22s           %7lu %10lu\n",
>> -	   "Total", info.total_created, info.total_allocated);
>> -  fprintf (stderr, "--------------------------------------------------------------------------------------------------------------\n");
>> +  pool_allocator_usage.dump (ALLOC_POOL);
>>  }
>> diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h
>> index 96a1342..a1727ce 100644
>> --- a/gcc/alloc-pool.h
>> +++ b/gcc/alloc-pool.h
>> @@ -26,6 +26,71 @@ extern void dump_alloc_pool_statistics (void);
>>  
>>  typedef unsigned long ALLOC_POOL_ID_TYPE;
>>  
>> +/* Pool allocator memory usage.  */
>> +struct pool_usage: public mem_usage
>> +{
>> +  /* Default contructor.  */
>> +  pool_usage (): m_element_size (0), m_pool_name ("") {}
>> +  /* Constructor.  */
>> +  pool_usage (size_t allocated, size_t times, size_t peak,
>> +	      size_t instances, size_t element_size,
>> +	      const char *pool_name)
>> +    : mem_usage (allocated, times, peak, instances),
>> +      m_element_size (element_size),
>> +      m_pool_name (pool_name) {}
>> +
>> +  /* Sum the usage with SECOND usage.  */
>> +  pool_usage operator+ (const pool_usage &second)
>> +  {
>> +    return pool_usage (m_allocated + second.m_allocated,
>> +			     m_times + second.m_times,
>> +			     m_peak + second.m_peak,
>> +			     m_instances + second.m_instances,
>> +			     m_element_size, m_pool_name);
>> +  }
>> +
>> +  /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
>> +  inline void dump (mem_location *loc, mem_usage &total) const
>> +  {
>> +    char s[4096];
>> +    sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
>> +	     loc->m_line, loc->m_function);
>> +
>> +    s[48] = '\0';
>> +
>> +    fprintf (stderr, "%-32s%-48s %6li%10li:%5.1f%%%10li%10li:%5.1f%%%12li\n",
>> +	     m_pool_name, s, (long)m_instances,
>> +	     (long)m_allocated, get_percent (m_allocated, total.m_allocated),
>> +	     (long)m_peak, (long)m_times,
>> +	     get_percent (m_times, total.m_times),
>> +	     (long)m_element_size);
>> +  }
>> +
>> +  /* Dump header with NAME.  */
>> +  static inline void dump_header (const char *name)
>> +  {
>> +    fprintf (stderr, "%-32s%-48s %6s%11s%16s%17s%12s\n", "Pool name", name,
>> +	     "Pools", "Leak", "Peak", "Times", "Elt size");
>> +    print_dash_line ();
>> +  }
>> +
>> +  /* Dump footer.  */
>> +  inline void dump_footer ()
>> +  {
>> +    print_dash_line ();
>> +    fprintf (stderr, "%s%75li%10li\n", "Total", (long)m_instances,
>> +	     (long)m_allocated);
>> +    print_dash_line ();
>> +  }
>> +
>> +  /* Element size.  */
>> +  size_t m_element_size;
>> +  /* Pool name.  */
>> +  const char *m_pool_name;
>> +};
>> +
>> +extern mem_alloc_description<pool_usage> pool_allocator_usage;
>> +
>>  /* Type based memory pool allocator.  */
>>  template <typename T>
>>  class pool_allocator
>> @@ -35,7 +100,7 @@ public:
>>       has NUM elements.  The allocator support EXTRA_SIZE and can
>>       potentially IGNORE_TYPE_SIZE.  */
>>    pool_allocator (const char *name, size_t num, size_t extra_size = 0,
>> -		  bool ignore_type_size = false);
>> +		  bool ignore_type_size = false CXX_MEM_STAT_INFO);
>>    ~pool_allocator ();
>>    void release ();
>>    void release_if_empty ();
>> @@ -122,6 +187,8 @@ private:
>>    size_t m_extra_size;
>>    /* Flag if a pool allocator is initialized.  */
>>    bool m_initialized;
>> +  /* Memory allocation location.  */
>> +  mem_location m_location;
>>  };
>>  
>>  /* Last used ID.  */
>> @@ -151,19 +218,16 @@ struct alloc_pool_descriptor
>>  /* Hashtable mapping alloc_pool names to descriptors.  */
>>  extern hash_map<const char *, alloc_pool_descriptor> *alloc_pool_hash;
>>  
>> -/* For given name, return descriptor, create new if needed.  */
>> -alloc_pool_descriptor *
>> -allocate_pool_descriptor (const char *name);
>> -
>>  template <typename T>
>>  inline
>>  pool_allocator<T>::pool_allocator (const char *name, size_t num,
>> -				   size_t extra_size, bool ignore_type_size):
>> +				   size_t extra_size, bool ignore_type_size
>> +				   MEM_STAT_DECL):
>>    m_name (name), m_elts_per_block (num), m_returned_free_list (NULL),
>>    m_virgin_free_list (NULL), m_virgin_elts_remaining (0), m_elts_allocated (0),
>>    m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL),
>>    m_ignore_type_size (ignore_type_size), m_extra_size (extra_size),
>> -  m_initialized (false) {}
>> +  m_initialized (false), m_location (ALLOC_POOL, false PASS_MEM_STAT) {}
>>  
>>  /* Initialize a pool allocator.  */
>>  
>> @@ -196,9 +260,11 @@ pool_allocator<T>::initialize ()
>>  
>>    if (GATHER_STATISTICS)
>>      {
>> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
>> -      desc->elt_size = size;
>> -      desc->created++;
>> +      pool_usage *u = pool_allocator_usage.register_descriptor
>> +	(this, new mem_location (m_location));
>> +
>> +      u->m_element_size = m_elt_size;
>> +      u->m_pool_name = m_name;
>>      }
>>  
>>    /* List header size should be a multiple of 8.  */
>> @@ -235,10 +301,10 @@ pool_allocator<T>::release ()
>>        free (block);
>>      }
>>  
>> -  if (GATHER_STATISTICS && false)
>> +  if (GATHER_STATISTICS)
>>      {
>> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
>> -      desc->current -= (m_elts_allocated - m_elts_free) * m_elt_size;
>> +      pool_allocator_usage.release_instance_overhead (this,
>> +	(m_elts_allocated - m_elts_free) * m_elt_size);
>>      }
>>  
>>    m_returned_free_list = NULL;
>> @@ -279,12 +345,7 @@ pool_allocator<T>::allocate ()
>>  
>>    if (GATHER_STATISTICS)
>>      {
>> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
>> -
>> -      desc->allocated += m_elt_size;
>> -      desc->current += m_elt_size;
>> -      if (desc->peak < desc->current)
>> -	desc->peak = desc->current;
>> +      pool_allocator_usage.register_instance_overhead (m_elt_size, this);
>>      }
>>  
>>  #ifdef ENABLE_VALGRIND_ANNOTATIONS
>> @@ -383,8 +444,7 @@ pool_allocator<T>::remove (T *object)
>>  
>>    if (GATHER_STATISTICS)
>>      {
>> -      alloc_pool_descriptor *desc = allocate_pool_descriptor (m_name);
>> -      desc->current -= m_elt_size;
>> +      pool_allocator_usage.release_instance_overhead (this, m_elt_size);
>>      }
>>  }
>>  
>> diff --git a/gcc/mem-stats-traits.h b/gcc/mem-stats-traits.h
>> index de1614e..f7843f2 100644
>> --- a/gcc/mem-stats-traits.h
>> +++ b/gcc/mem-stats-traits.h
>> @@ -10,11 +10,12 @@ enum mem_alloc_origin
>>    VEC,
>>    BITMAP,
>>    GGC,
>> +  ALLOC_POOL,
>>    MEM_ALLOC_ORIGIN_LENGTH
>>  };
>>  
>>  /* Verbose names of the memory allocation origin.  */
>>  static const char * mem_alloc_origin_names[] = { "Hash tables", "Hash maps",
>> -  "Hash sets", "Heap vectors", "Bitmaps", "GGC memory" };
>> +  "Hash sets", "Heap vectors", "Bitmaps", "GGC memory", "Allocation pool" };
>>  
>>  #endif // GCC_MEM_STATS_TRAITS_H
>> diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h
>> index ac47231..fea68fa 100644
>> --- a/gcc/mem-stats.h
>> +++ b/gcc/mem-stats.h
>> @@ -18,11 +18,16 @@ struct mem_location
>>    inline mem_location () {}
>>  
>>    /* Constructor.  */
>> -  inline mem_location (const char *filename, const char *function, int line,
>> -		mem_alloc_origin origin, bool ggc):
>> +  inline mem_location (mem_alloc_origin origin, bool ggc,
>> +		const char *filename = NULL, int line = 0, const char *function = NULL):
>>      m_filename (filename), m_function (function), m_line (line), m_origin
>>      (origin), m_ggc (ggc) {}
>>  
>> +  /* Copy constructor.  */
>> +  inline mem_location (mem_location &other): m_filename (other.m_filename),
>> +    m_function (other.m_function), m_line (other.m_line),
>> +    m_origin (other.m_origin), m_ggc (other.m_ggc) {}
>> +
>>    /* Compute hash value based on file name, function name and line in
>>       source code. As there is just a single pointer registered for every
>>       constant that points to e.g. the same file name, we can use hash
>> @@ -79,11 +84,12 @@ struct mem_location
>>  struct mem_usage
>>  {
>>    /* Default constructor.  */
>> -  mem_usage (): m_allocated (0), m_times (0), m_peak (0) {}
>> +  mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {}
>>  
>>    /* Constructor.  */
>> -  mem_usage (size_t allocated, size_t times, size_t peak):
>> -    m_allocated (allocated), m_times (times), m_peak (peak) {}
>> +  mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0):
>> +    m_allocated (allocated), m_times (times), m_peak (peak),
>> +    m_instances (instances) {}
>>  
>>    /* Register overhead of SIZE bytes.  */
>>    inline void register_overhead (size_t size)
>> @@ -108,7 +114,8 @@ struct mem_usage
>>    {
>>      return mem_usage (m_allocated + second.m_allocated,
>>  		      m_times + second.m_times,
>> -		      m_peak + second.m_peak);
>> +		      m_peak + second.m_peak,
>> +		      m_instances + second.m_instances);
>>    }
>>  
>>    /* Comparison operator.  */
>> @@ -163,7 +170,7 @@ struct mem_usage
>>    /* Print line made of dashes.  */
>>    static inline void print_dash_line ()
>>    {
>> -    fprintf (stderr, "%s\n", std::string (128, '-').c_str ());
>> +    fprintf (stderr, "%s\n", std::string (140, '-').c_str ());
>>    }
>>  
>>    /* Dump header with NAME.  */
>> @@ -180,6 +187,8 @@ struct mem_usage
>>    size_t m_times;
>>    /* Peak allocation in bytes.  */
>>    size_t m_peak;
>> +  /* Number of container instances.  */
>> +  size_t m_instances;
>>  };
>>  
>>  /* Memory usage pair that connectes memory usage and number
>> @@ -241,9 +250,13 @@ public:
>>    /* Return descriptor for instance PTR.  */
>>    T *get_descriptor_for_instance (const void *ptr);
>>  
>> -  /* Register memory allocation descriptor for container PTR. ORIGIN identifies
>> +  /* Register memory allocation descriptor for container PTR which is
>> +     described by a memory LOCATION.  */
>> +  T *register_descriptor (const void *ptr, mem_location *location);
>> +
>> +  /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
>>       type of container and GGC identifes if the allocation is handled in GGC
>> -     memory. Each location is identified by file NAME, LINE in source code and
>> +     memory.  Each location is identified by file NAME, LINE in source code and
>>       FUNCTION name.  */
>>    T *register_descriptor (const void *ptr, mem_alloc_origin origin,
>>  			  bool ggc, const char *name, int line,
>> @@ -321,33 +334,27 @@ mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
>>    return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
>>  }
>>  
>> -/* Register memory allocation descriptor for container PTR. ORIGIN identifies
>> -   type of container and GGC identifes if the allocation is handled in GGC
>> -   memory. Each location is identified by file NAME, LINE in source code and
>> -   FUNCTION name.  */
>>  
>> +  /* Register memory allocation descriptor for container PTR which is
>> +     described by a memory LOCATION.  */
>>  template <class T>
>>  inline T*
>>  mem_alloc_description<T>::register_descriptor (const void *ptr,
>> -					       mem_alloc_origin origin,
>> -					       bool ggc,
>> -					       const char *filename,
>> -					       int line,
>> -					       const char *function)
>> +					       mem_location *location)
>>  {
>> -  mem_location *l = new mem_location (filename, function, line, origin, ggc);
>>    T *usage = NULL;
>>  
>> -  T **slot = m_map->get (l);
>> +  T **slot = m_map->get (location);
>>    if (slot)
>>      {
>> -      delete l;
>> +      delete location;
>>        usage = *slot;
>> +      usage->m_instances++;
>>      }
>>    else
>>      {
>>        usage = new T ();
>> -      m_map->put (l, usage);
>> +      m_map->put (location, usage);
>>      }
>>  
>>    if (!m_reverse_map->get (ptr))
>> @@ -356,6 +363,24 @@ mem_alloc_description<T>::register_descriptor (const void *ptr,
>>    return usage;
>>  }
>>  
>> +/* Register memory allocation descriptor for container PTR.  ORIGIN identifies
>> +   type of container and GGC identifes if the allocation is handled in GGC
>> +   memory.  Each location is identified by file NAME, LINE in source code and
>> +   FUNCTION name.  */
>> +
>> +template <class T>
>> +inline T*
>> +mem_alloc_description<T>::register_descriptor (const void *ptr,
>> +					       mem_alloc_origin origin,
>> +					       bool ggc,
>> +					       const char *filename,
>> +					       int line,
>> +					       const char *function)
>> +{
>> +  mem_location *l = new mem_location (origin, ggc, filename, line, function);
>> +  return register_descriptor (ptr, l);
>> +}
>> +
>>  /* Register instance overhead identified by PTR pointer. Allocation takes
>>     SIZE bytes.  */
>>  
>>
> 
> Hello.
> 
> There's a small patch that fixes ICE if a compiler is not built with --enable-gather-mem-stats
> and we append -fmem-report to a command line options.
> 
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> 
> Ready for trunk?
> Thanks,
> Martin
> 

Honza approved the patch. I'm going to install the patch.

Martin
diff mbox

Patch

From 0d0e2cabf7f6946b319788ebb884c0e9e35790bd Mon Sep 17 00:00:00 2001
From: mliska <mliska@suse.cz>
Date: Mon, 8 Jun 2015 10:39:12 +0200
Subject: [PATCH] Fallout for new memory statistics infrastructure.

gcc/ChangeLog:

2015-06-08  Martin Liska  <mliska@suse.cz>

	* bitmap.c (dump_bitmap_statistics): Fix GNU coding style.
	* hash-table.c (void dump_hash_table_loc_statistics): Add missing
	guard.
---
 gcc/bitmap.c     | 2 +-
 gcc/hash-table.c | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index 5fc4654..20a093c 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -2079,7 +2079,7 @@  bitmap_print (FILE *file, const_bitmap head, const char *prefix,
 void
 dump_bitmap_statistics (void)
 {
-  if (! GATHER_STATISTICS)
+  if (!GATHER_STATISTICS)
     return;
 
   bitmap_mem_desc.dump (BITMAP);
diff --git a/gcc/hash-table.c b/gcc/hash-table.c
index 012b241..ee972e7 100644
--- a/gcc/hash-table.c
+++ b/gcc/hash-table.c
@@ -103,6 +103,9 @@  mem_alloc_description<mem_usage> hash_table_usage;
 /* Support function for statistics.  */
 void dump_hash_table_loc_statistics (void)
 {
+  if (!GATHER_STATISTICS)
+    return;
+
   for (unsigned i = HASH_TABLE; i <= HASH_SET; i++)
     {
       mem_alloc_origin origin = (mem_alloc_origin) i;
-- 
2.1.4