Port pool-allocator memory stats to a new infrastructure.
authorMartin Liska <mliska@suse.cz>
Wed, 3 Jun 2015 09:33:32 +0000 (11:33 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Wed, 3 Jun 2015 09:33:32 +0000 (09:33 +0000)
* 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
* mem-stats.h (mem_location::to_string): New function.
* bitmap.h (struct bitmap_usage): Use this new function.
* ggc-common.c (struct ggc_usage): Likewise.
the function.

From-SVN: r224070

gcc/ChangeLog
gcc/alloc-pool.c
gcc/alloc-pool.h
gcc/bitmap.h
gcc/ggc-common.c
gcc/mem-stats-traits.h
gcc/mem-stats.h

index 390ea0f171e25415ea0c3099ced0095614c6862d..0a18c89d5606def4f9f057d5f47335f32b1c4831 100644 (file)
@@ -1,3 +1,26 @@
+2015-06-03  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
+       * mem-stats.h (mem_location::to_string): New function.
+       * bitmap.h (struct bitmap_usage): Use this new function.
+       * ggc-common.c (struct ggc_usage): Likewise.
+       the function.
+
 2015-06-03  Richard Sandiford  <richard.sandiford@arm.com>
 
        * defaults.h (SWITCHABLE_TARGET, TARGET_SUPPORTS_WIDE_INT): Move out
index e9fdc86b01675d6ba026f9cb07e0f481d38304b5..601c2b73f817d54e5380c7f624a766550b6a5e84 100644 (file)
@@ -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);
 }
index ddb2a911df4f25fffa3daf5dff47a52ba42b9ff3..b1bd386156ba6d812c661276dd470f27723d9109 100644 (file)
@@ -26,6 +26,69 @@ 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 *location_string = loc->to_string ();
+
+    fprintf (stderr, "%-32s%-48s %6li%10li:%5.1f%%%10li%10li:%5.1f%%%12li\n",
+            m_pool_name, location_string, (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);
+
+    free (location_string);
+  }
+
+  /* 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 +98,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 +185,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 +216,17 @@ 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_id (0), 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_block_size (0), m_ignore_type_size (ignore_type_size),
-  m_extra_size (extra_size), m_initialized (false) {}
+  m_extra_size (extra_size), m_initialized (false),
+  m_location (ALLOC_POOL, false PASS_MEM_STAT) {}
 
 /* Initialize a pool allocator.  */
 
@@ -196,9 +259,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.  */
@@ -234,10 +299,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;
@@ -278,12 +343,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
@@ -382,8 +442,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);
     }
 }
 
index 40562f64c3493a4aa8dfa488955a063f72f026b2..4309f6db182c42e9600bce2e5c93f52de11a5bec 100644 (file)
@@ -156,18 +156,17 @@ struct bitmap_usage: public mem_usage
   /* 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);
+    char *location_string = loc->to_string ();
 
-    s[48] = '\0';
-
-    fprintf (stderr, "%-48s %10li:%5.1f%%%10li%10li:%5.1f%%%12li%12li%10s\n", s,
+    fprintf (stderr, "%-48s %10li:%5.1f%%%10li%10li:%5.1f%%%12li%12li%10s\n",
+            location_string,
             (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_nsearches, (long)m_search_iter,
             loc->m_ggc ? "ggc" : "heap");
+
+    free (location_string);
   }
 
   /* Dump header with NAME.  */
index 2e94ca4a6ef0d6742d9d09ecfea0df34314de36e..43ccc0b740208bd3c037e906dd074bc8eecd95b5 100644 (file)
@@ -894,12 +894,11 @@ struct ggc_usage: public mem_usage
   /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
   inline void dump (mem_location *loc, ggc_usage &total) const
   {
-    char s[4096];
-    sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
-            loc->m_line, loc->m_function);
-    s[48] = '\0';
+    char *location_string = loc->to_string ();
 
-    dump (s, total);
+    dump (location_string, total);
+
+    free (location_string);
   }
 
   /* Dump footer.  */
index de1614e49d63bff7fa62b592f38da04ad3b6200d..f7843f2165ff2becadc6234a015b6fde7b09ebbe 100644 (file)
@@ -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
index ac472315fd39c48f409b38eb7356a18cc1e536c3..092bfd3610e1ecd546d7c4564a0c61e166819254 100644 (file)
@@ -11,6 +11,9 @@ template<typename Key, typename Value,
         typename Traits = default_hashmap_traits>
 class hash_map;
 
+#define LOCATION_LINE_EXTRA_SPACE 30
+#define LOCATION_LINE_WIDTH      48
+
 /* Memory allocation location.  */
 struct mem_location
 {
@@ -18,11 +21,17 @@ 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
@@ -57,6 +66,20 @@ struct mem_location
     return s1;
   }
 
+  inline char *to_string ()
+  {
+    unsigned l = strlen (get_trimmed_filename ()) + strlen (m_function)
+      + LOCATION_LINE_EXTRA_SPACE;
+
+    char *s = XNEWVEC (char, l);
+    sprintf (s, "%s:%i (%s)", get_trimmed_filename (),
+            m_line, m_function);
+
+    s[MIN (LOCATION_LINE_WIDTH, l - 1)] = '\0';
+
+    return s;
+  }
+
   /* Return display name associated to ORIGIN type.  */
   static const char *get_origin_name (mem_alloc_origin origin)
   {
@@ -79,11 +102,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 +132,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.  */
@@ -133,20 +158,19 @@ struct mem_usage
   /* 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);
+    char *location_string = loc->to_string ();
 
-    s[48] = '\0';
-
-    fprintf (stderr, "%-48s %10li:%5.1f%%%10li%10li:%5.1f%%%10s\n", s,
+    fprintf (stderr, "%-48s %10li:%5.1f%%%10li%10li:%5.1f%%%10s\n",
+            location_string,
             (long)m_allocated, get_percent (m_allocated, total.m_allocated),
             (long)m_peak, (long)m_times,
             get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap");
+
+    free (location_string);
   }
 
   /* Dump footer.  */
-  inline void dump_footer ()
+  inline void dump_footer () const
   {
     print_dash_line ();
     fprintf (stderr, "%s%54li%27li\n", "Total", (long)m_allocated,
@@ -163,7 +187,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 +204,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 +267,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 +351,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 +380,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.  */